If there is a need to check for update, then equals alone is not enough. To understand that the object is "updated", you need to assign it a unique identifier and perform a comparison already on it. Those. as I understand depcode is this identifier.
The updated Position class and the wrapper class of the resulting collections:
static final class Position { //Мне кажется не очень правильным оставлять возможность менять идентификатор объекта! //Поэтому я удалил set метод и сделал значение final, т.е. константой. protected final String depcode; protected String depjob; protected String description; public Position(String depcode, String depjob, String description) { this.depcode = depcode; this.depjob = depjob; this.description = description; } //Здесь сравнение идет только по идентификатору @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Position)) return false; Position position = (Position) o; return getDepcode().equals(position.getDepcode()); } @Override public int hashCode() { return getDepcode().hashCode(); } //Доп. метод для сравнения остальных данных класса public boolean otherEquals(Position p){ return this.getDepjob().equals(p.getDepjob()) && this.getDescription().equals(p.getDescription()); } public String getDepcode() { return depcode; } public String getDepjob() { return depjob; } public void setDepjob(String depjob) { this.depjob = depjob; } public String getDescription() { return description; } @Override public String toString() { return "Position{" + "depcode='" + depcode + '\'' + ", depjob='" + depjob + '\'' + ", description='" + description + '\'' + '}'; } } //Класс-обертка для результата static final class Delta{ final Collection<Position> added; final Collection<Position> deleted; final Collection<Position> updated; public Delta(Collection<Position> added, Collection<Position> deleted, Collection<Position> updated) { this.added = added; this.deleted = deleted; this.updated = updated; } }
Method to get a "delta":
public static Delta getDelta(Set<Position> from, Set<Position> to){ //Копируем списки из исходных. //Если данные из старого больше не нужны, то его копирование можно пропустить Set<Position> fromCopy = new HashSet<>(from); Set<Position> toCopy = new HashSet<>(to); Collection<Position> updated = null; //Получаем итераторы. Работаем с ними, потому, что будем удалять из списков final Iterator<Position> fromIterator = fromCopy.iterator(); //Проходим по старым данным while (fromIterator.hasNext()){ //Флаг того, что совпадение было найдено boolean found = false; final Position fromPos = fromIterator.next(); final Iterator<Position> toIterator = toCopy.iterator(); while (toIterator.hasNext()){ final Position toPos = toIterator.next(); //Если совпадают идентификаторы if (fromPos.equals(toPos)) { //При этом, если не совпадает содержание if (!fromPos.otherEquals(toPos)){ //Если список апдейтов еще не инициализирован, то делам это if (updated == null) updated = new ArrayList<>(); //Добавляем значение updated.add(toPos); //Удаляем это значение из списка по которому проходим, т.к. оно нам больше не понадобится. //И в конце, в данном списке останутся только added элементы toIterator.remove(); } //Устанавливаем флаг, чтобы удалить значение из списка from. //Получается, что в конечном счете в данном списке останутся только deleted элементы found = true; } } if (found) fromIterator.remove(); } //Проверяем, что хоть что-то осталось в списках //Если нет, то передаем специальный пустой список, чтобы занимать меньше места if (fromCopy.isEmpty()) fromCopy = Collections.emptySet(); if (toCopy.isEmpty()) toCopy = Collections.emptySet(); if (updated == null) updated = Collections.emptySet(); return new Delta(toCopy,fromCopy,updated); }
Testing:
public static void main(String[] args) { Position old1 = new Position("1","some","desc"); Position old2 = new Position("2","some1","desc1"); Position old3 = new Position("3","some2","desc2"); Position new1 = new Position("1","someNew","desc"); Position new2 = new Position("2","some1","newDesc"); Position new3 = new Position("4","some3","desc3"); Set<Position> from = new HashSet<>(); from.add(old1);from.add(old2);from.add(old3); Set<Position> to = new HashSet<>(); to.add(new1);to.add(new2);to.add(new3); Delta d = getDelta(from,to); System.out.println("Added positions:"); d.added.forEach(System.out::println); System.out.println("\nDeleted positions:"); d.deleted.forEach(System.out::println); System.out.println("\nUpdated positions:"); d.updated.forEach(System.out::println); }
Result:
Added positions: Position {depcode = '4', depjob = 'some3', description = 'desc3'}
Deleted positions: Position {depcode = '3', depjob = 'some2', description = 'desc2'}
Updated positions: Position {depcode = '1', depjob = 'someNew', description = 'desc'} Position {depcode = '2', depjob = 'some1', description = 'newDesc'}
toDeleteand totoAddon the basis of the number of elements in the collections, and not on the basis of the differences between them. - Regentequals, then you can loop in a loop: in the outer loop, go over the elements of one collection, in the inner cycle - another. And, in fact, compare the elements. One such cycle of cycles for add, another - for delete. What elements should fall into the update - it is not clear. - Regent