Как найти соответствующие объекты между двумя списками? - PullRequest
8 голосов
/ 16 февраля 2011

Учитывая два списка, каждый список содержит один и тот же тип объекта, я хотел бы найти объекты между двумя соответствующими списками, основываясь на некоторых значениях свойств.

например. объект из List1, L1Obj, соответствует объекту из List2, L2Obj, если L1Obj.a == L2Obj.a AND L1Obj.b == L2Obj.c AND L1Obj.c == L2Obj.c

Эти свойства не являются единственными свойствами класса, но это все, что необходимо для уникальной идентификации объекта в списке.

У меня вопрос - как лучше всего этого добиться?

Одним из способов было бы создание HashMaps на основе списков с конкатанированным значением String a + b + c, используемым в качестве ключа для индексации объекта. Таким образом, я мог бы перебрать первый список и попытаться найти объект во втором списке с тем же ключом.

Как это звучит? Есть ли лучший способ добиться этого ??

Вся помощь очень ценится!


UPDATE:

Хорошо, так что на самом деле мне нужно немного больше. Найдя совпадение, я хочу перезаписать свойства L1Obj.x, L1Obj.y, L1Obj.z на свойства L2Obj. HashSet отлично подходит для поиска совпадений, но, если я прав, он не позволяет мне получить доступ к этим совпадениям.

Что я могу с этим поделать?

Ответы [ 5 ]

8 голосов
/ 16 февраля 2011

Реализуют ли объекты, которые вы хотите посмотреть, equals(Object) и hashCode(), которые учитывают только те поля, которые вас интересуют?Если это так, вы можете создать новый HashSet из первого списка, а затем вызвать retainAll(), передавая во второй список.

Если они не реализуют equals(Object) и hashCode() относительносвойства, которые вас интересуют, вы можете создать TreeSet и передать Comparator, который просматривает свойства, которые вас интересуют.

3 голосов
/ 16 февраля 2011

Вместо использования представления String используйте метод equals() для HashSet следующим образом:

class MyObj {

    Property a;
    Property b;
    Property c;

    public boolean equals(Object o) {
        // use == if Property is primitive, like int or something
        return o instanceof MyObj && a.equals(o.a) && b.equals(o.b) && c.equals(o.c);
    }

    // edit - when you override equals, also override hashcode
    public int hashCode() {
        return a.hashCode() ^ b.hashCode() ^ c.hashCode();
    }

    public String toString() {
        return a.toString() + " " + b.toString() + " " + c.toString();
    }

}

// later in your main method
Set<MyObj> objSet = new HashSet<MyObj>();
for(MyObj o : list1) objSet.add(o);
for(MyObj o : list2) if(objSet.contains(o)) System.out.println(o + " is a match!");
1 голос
/ 16 февраля 2011

Вы можете сделать одну вещь.Иметь два списка с этими объектами и переопределить метод equals класса, к которому принадлежат эти объекты.Ваш метод equals должен выглядеть следующим образом:

@Override
public boolean equals(Object obj)
{
    return (this.a == obj.a && this.b == obj.b && this.c == obj.c)

}

Также помните, что после переопределения метода equals вам также необходимо переопределить метод int hashCode ().

При реализации hashCode необходимо отметить одну вещь() состоит в том, что 2 равных объекта будут иметь одинаковый hashCode, в то время как обратное неверно.

0 голосов
/ 16 февраля 2011

Рассматриваемый объект должен реализовывать метод boolean equals(Object). E.g.:

 L1Obj.equals(L2Obj);

Вы можете перегрузить этот метод, чтобы реализовать требуемые операции равенства.

0 голосов
/ 16 февраля 2011

Я не знаю, думаю ли я просто, но я бы попробовал это так:

Переопределите метод equals объекта, чтобы реализовать сравнение, чтобы проверить, является ли это тот же объект

Затем я перебрал бы первый список и проверил бы с помощью метода contains, содержится ли объект во втором списке.

Затем я перебрал бы второй список и проверил, находится ли объект также впервый список и еще не в списке результатов.

...