There are two collections:

Set<Position> set1 = new HashSet<>(); Set<Position> set2 = new HashSet<>(); 

and Position class:

 public class Position { protected 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; } public String getDepcode() { return depcode; } public void setDepcode(String depcode) { this.depcode = depcode; } public String getDepjob() { return depjob; } public void setDepjob(String depjob) { this.depjob = depjob; } public String getDescription() { return description; } } 

It is necessary to compare and synchronize set1 by set2. If there are more elements in set1 than in set2, then add extra data to the toDelete collection. If less, in the tpAdd collection, and also the modified ones add to toUpdate.

 Set<Position> toDelete = new HashSet<>(); Set<Position> toAdd = new HashSet<>(); Set<Position> toUpdate = new HashSet<>(); 
  • 2
    And what is the question, and with what problem did you have? - Regent
  • 3
    It is rather strange, in my opinion, to add to toDelete and to toAdd on the basis of the number of elements in the collections, and not on the basis of the differences between them. - Regent
  • Add need for differences agree. You must do this with the equals method. The question is how to pull this difference in collections. I ask you not to perform, but suggest how to do it - Kh.Bu
  • I recommend reading Joshua Boch "Java. Effective programming", 2nd edition (Joshua Bloch. Effective Java), namely: Chapter 3, articles 8-9, at the same time and learn about all sorts of nuances. And in general, this book is strongly recommended to study all. - Just So
  • @ Kh.Bu so here you have in the text of the question only the task and there is not a word about the question itself. If you need to do it with the help of equals , 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

2 answers 2

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'}

  • Thanks for the example. Clearly and clearly) - Kh.Bu

I got the following solution:

 Set<Position> toDelete = Collections.emptySet(); Set<Position> toAdd = Collections.emptySet(); Set<Position> toUpdate = new HashSet<>(); //ищем записи которые не равны между собой //но у которых совпадает, хотя бы одно поле for (Position oldPos : oldPositions) for (Position newPos : newPositions) if (!oldPos.equals(newPos) && oldPos.otherEquals(newPos)) toUpdate.add(oldPos); //ищем записи содержащиеся только //в множестве "старых" записей Set<Position> buffer = new HashSet<>(oldPositions); if (buffer.removeAll(newPositions)) { buffer.removeAll(toUpdate); toDelete = buffer; } //ищем записи содержащиеся только //в множестве "новых" записей //удаляем из них те, которые добавлены на "обновление" buffer = new HashSet<>(newPositions); if (buffer.removeAll(oldPositions)) { buffer.removeIf(position -> toUpdate.stream().anyMatch(e -> e.otherEquals(position))); toAdd = buffer; } System.out.println("for add: " + toAdd); System.out.println("for delete: " + toDelete); System.out.println("for update: " + toUpdate); 

In the Position class, you need to override the hashCode and equals methods for HashSet work correctly.

 class Position { String depcode; String depjob; String description; //other methods @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Position position = (Position) o; if (depcode != null ? !depcode.equals(position.depcode) : position.depcode != null) return false; if (depjob != null ? !depjob.equals(position.depjob) : position.depjob != null) return false; return description != null ? description.equals(position.description) : position.description == null; } @Override public int hashCode() { int result = depcode != null ? depcode.hashCode() : 0; result = 31 * result + (depjob != null ? depjob.hashCode() : 0); result = 31 * result + (description != null ? description.hashCode() : 0); return result; } public boolean otherEquals(Position other) { return Objects.equals(this.depcode, other.depcode) || Objects.equals(this.depjob, other.depjob) || Objects.equals(this.description, other.description); } } 

Test:

 Position n1 = new Position("1", "s1", "desc1"); Position n2 = new Position("2", "s2", "desc2"); Position n3 = new Position("3", "s3", "desc3"); //запись на добавление Position n4 = new Position("4", "s4", "this entry for add"); //запись на обновление Position n5 = new Position("5", "s5", "new description"); Position o1 = new Position("1", "s1", "desc1"); Position o2 = new Position("2", "s2", "desc2"); Position o3 = new Position("3", "s3", "desc3"); //запись на обновление Position o5 = new Position("5", "s5", "old description"); //запись на удаление Position o4 = new Position("6", "s6", "this entry for remove"); 

The output will be as follows:

for add: [Position {depcode = '4', depjob = 's4', description = 'this entry for add'}]
for delete: [Position {depcode = '6', depjob = 's6', description = 'this entry for remove'}]
for update: [Position {depcode = '5', depjob = 's5', description = 'old description'}]