Синхронизация коллекций HashSet java

372
14 февраля 2017, 18:39

Есть две коллекции:

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

и класс Position:

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

Необходимо сравнить и синхронизовать set1 по set2. Eсли элементов в set1 больше чем в set2, то лишние данные добавить в коллекцию toDelete. Если меньше, в коллекцию tpAdd, а также измененные добавить в toUpdate.

Set<Position> toDelete = new HashSet<>();
Set<Position> toAdd = new HashSet<>();
Set<Position> toUpdate = new HashSet<>();
Answer 1

Если есть необходимость проверять на update, то одним equals не обойтись. Чтобы понимать, что объект "апдейтнулся", необходимо присвоить ему однозначный идентификатор и выполнять сравнение уже по нему. Т.е. как я понял depcode и есть этот идентификатор.

Обновленный класс Position и класс-обертка результирующих коллекций:

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

Метод для получения "дельты":

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);
}    

Тестируем:

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);
}

Результат:

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

READ ALSO
XSD Java: получить структуру

XSD Java: получить структуру

Всем добрый деньВстала задача из XSD получить результирующую структуру XML

429
Как импортировать библиотеку twoway-view?

Как импортировать библиотеку twoway-view?

Есть такая библиотека twoway-view которая позволяет создать кастомный recycler view как мне нужно

428
netty ArrayIndexOutOfBoundsException: 1

netty ArrayIndexOutOfBoundsException: 1

Добрый день! Я новичок в программировании, осваиваю java и netty 4Пишу небольшое клиент-серверное приложение с использованием netty

371
Как отображать временные данные?

Как отображать временные данные?

Я создал сайт вопросов и хочу при ответе пользователя на вопросы сделать клик на варианты radio buttonВыбранный вариант должен загрузиться во временную...

342