Assuming you have all the necessary getters and have overriden the equals and hashCode methods, for example like this:
class Position {
String account;
String Date;
String Cycle;
String Status;
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final Position position = (Position) o;
return Objects.equals(account, position.account) && Objects.equals(Date, position.Date)
&& Objects.equals(Cycle, position.Cycle) && Objects.equals(Status, position.Status);
}
@Override
public int hashCode() {
return Objects.hash(account, Date, Cycle, Status);
}
}
You could stream over both lists, order them in an identical way and group them by account and use the resulting maps to filter accounts having the same list of Position objects. Example code:
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;
public class Example2 {
public static void main(String[] args) {
List<Position> listA = List.of(new Position("ACC1", "20-Jan-23", "1", "open"),
new Position("ACC1", "20-Jan-23", "2", "closing"),
new Position("ACC2", "20-Jan-23", "1", "open"),
new Position("ACC2", "20-Jan-23", "2", "closing"),
new Position("ACC3", "20-Jan-23", "1", "open"),
new Position("ACC3", "20-Jan-23", "2", "closing"));
List<Position> listB = List.of(new Position("ACC1", "20-Jan-23", "1", "open"),
new Position("ACC1", "20-Jan-23", "2", "closing"),
new Position("ACC2", "20-Jan-23", "1", "open"),
new Position("ACC2", "20-Jan-23", "2", "closed"),
new Position("ACC3", "20-Jan-23", "1", "open"));
Comparator<Position> comparator = Comparator.comparing(Position::getAccount)
.thenComparing(Position::getDate)
.thenComparing(Position::getCycle)
.thenComparing(Position::getStatus);
Map<String, List<Position>> mapA = listA.stream().sorted(comparator).collect(Collectors.groupingBy(Position::getAccount));
Map<String, List<Position>> mapB = listB.stream().sorted(comparator).collect(Collectors.groupingBy(Position::getAccount));
List<String> result = mapA.keySet()
.stream()
.filter(key -> mapA.get(key).equals(mapB.get(key)))
.toList();
System.out.println(result);
}
@AllArgsConstructor
@Getter
@ToString
static class Position {
String account;
String Date;
String Cycle;
String Status;
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final Position position = (Position) o;
return Objects.equals(account, position.account) && Objects.equals(Date, position.Date)
&& Objects.equals(Cycle, position.Cycle) && Objects.equals(Status, position.Status);
}
@Override
public int hashCode() {
return Objects.hash(account, Date, Cycle, Status);
}
}
}
UPDATE
..been told not to override equal and hascode method in PositionEntity... is there any other way to compare the equality of the 2 list of objects without using equals method?
you can do the field by field comparison manually. I have added an example using BiPredicates. May be there are some eleganter ways to do this with some 3rd party libraries. But without changing the first approach too much the below should give you the same result without the need to override equals and hashCode.
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.function.BiPredicate;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;
public class Example2 {
public static void main(String[] args) {
List<Position> listA = List.of(new Position("ACC1", "20-Jan-23", "1", "open"),
new Position("ACC1", "20-Jan-23", "2", "closing"),
new Position("ACC2", "20-Jan-23", "1", "open"),
new Position("ACC2", "20-Jan-23", "2", "closing"),
new Position("ACC3", "20-Jan-23", "1", "open"),
new Position("ACC3", "20-Jan-23", "2", "closing"));
List<Position> listB = List.of(new Position("ACC1", "20-Jan-23", "1", "open"),
new Position("ACC1", "20-Jan-23", "2", "closing"),
new Position("ACC2", "20-Jan-23", "1", "open"),
new Position("ACC2", "20-Jan-23", "2", "closed"),
new Position("ACC3", "20-Jan-23", "1", "open"));
Comparator<Position> comparator = Comparator.comparing(Position::getAccount)
.thenComparing(Position::getDate)
.thenComparing(Position::getCycle)
.thenComparing(Position::getStatus);
Map<String, List<Position>> mapA = listA.stream().sorted(comparator).collect(Collectors.groupingBy(Position::getAccount));
Map<String, List<Position>> mapB = listB.stream().sorted(comparator).collect(Collectors.groupingBy(Position::getAccount));
//Since you cannot modify equals and hashCode you can do the field by field comparison manually
//there are maybe some 3rd party libraries which might do this elegantly,
// but something like below should work fine
BiPredicate<Position,Position> positionsEqual = (position1, position2) ->
position1.getAccount().equals(position2.getAccount()) &&
position1.getDate().equals(position2.getDate()) &&
position1.getCycle().equals(position2.getCycle()) &&
position1.getStatus().equals(position2.getStatus());
//Same approach to test the equality of two lists index by index using above predicate
BiPredicate<List<Position>,List<Position>> listsEqual = (list1, list2) -> {
if (list1.size() != list2.size()){
return false;
}
return IntStream.range(0, list1.size()).allMatch(i -> positionsEqual.test(list1.get(i), list2.get(i)));
};
//using the predicate to filter
List<String> result = mapA.keySet()
.stream()
.filter(key -> listsEqual.test(mapA.get(key),(mapB.get(key))))
.toList();
System.out.println(result);
}
@AllArgsConstructor
@Getter
@ToString
static class Position {
String account;
String Date;
String Cycle;
String Status;
//Constructor, getter, toString..
}
}