4

我有两个列表,我想在其中执行批量操作,例如使用方法 removeAll、retainAll、contains。问题是这两个列表都有不同类型的对象,它们有一个相同的字段。就像是

class ObjectType1{
  Long field1;
  String field2;
  String field3
 }

class ObjectType2{
Long field1;
String field4;
Long field5

}

所以list1包含ObjectType1的元素,list2包含ObjectType2。我想基于 field1 进行批量操作,这在两种对象类型中都很常见。

我正在考虑在基于公共字段的两个对象中实现 equals 方法。但是后来认为仅在一个字段上进行等于可能是错误的,因为将来可能需要在等于方法中添加基于其他字段的比较。请建议。

希望我的查询足够清楚。请让我知道以进行澄清。

4

5 回答 5

1

看看 Google 的 Guava 库。您可以使用Collections2.transform来实现这一点。retainAll()例如,您可以这样做:

import com.google.common.base.Function;
import com.google.common.collect.Collections2;
...
List<ObjectType1> list1 = ...;
List<ObjectType2> list2 = ...;
Colection<Long> list1field1 = 
  Collections2.transform(list1, 
                         new Function<ObjectType1, Long>() {
                           public Long apply(ObjectType1 input) {
                             return (null == input) ? null : input.field1;
                           }
                         });
Collection<Long> list2field1 = 
  Collections2.transform(list2, ...);

// list1.retainAll(list2) based on field1 equivalence
list1field1.retainAll(list2field1); // this affects the underlying list, ie list1.
于 2013-02-13T07:48:42.330 回答
0

我已经使用接口编写了代码

public interface IMatchable {

    Object getMatchingField();
}

然后我的 ObjectType1 和 ObjectType2 正在实现这个接口以及重写 equals 方法

public class ObjectType1 implements IMatchable {

@Override
public Object getMatchingField() {
    return field1;
}
 @Override
 public boolean equals(Object obj) {
    IMatchable matchableObj = null;
    if (obj instanceof IMatchable) {
        matchableObj = (IMatchable) obj;
    } else {
        return false;
    }
    return matchableObj.getMatchingField().equals(this.getMatchingField()) ? true: false;
}
}

ObjectType2 与这些方法类似。

于 2013-02-13T07:31:04.310 回答
0

如果我理解你的问题是正确的,你想要类似的东西

    class SuperObject{
        Long field1;
        public SuperObject(){}
        public void setField1(Long f){
            field1 = f;
        }
        public Long getField1(){
            return field1;
        }
        public boolean equals(Object obj){
    if(obj instanceof SuperObject)
        return field1.equals(((SuperObject) obj).getField1());
    else
        return false;
}
    }
    class ObjectType1 extends SuperObject{
        String field2;
        String field3;
        ...    
}

    class ObjectType2 extends SuperObject{
        String field4;
        Long field5;
        ...
    }

列表应该类似于

List<SuperObject> list = new ArrayList<SuperObject>();
    ObjectType1 obj1 = new ObjectType1();
    ObjectType2 obj2 = new ObjectType2();
    list.add(obj1);
    list.add(obj2);

列表中的对象现在具有相同的相等方法实现,基于field1超类中的

于 2013-02-13T06:53:41.190 回答
0

试试下面的代码,它会给出常见值的列表

package rais;

import java.util.ArrayList;
import java.util.List;

public class ArrayClient {

    public static void main(String[] args) {

        List<ObjectType1> list1 = new ArrayList<ObjectType1>();

        ObjectType1 type1Obj1 = new ObjectType1(10001l, "XXX", "YYYY");
        list1.add(type1Obj1);

        ObjectType1 type1Obj2 = new ObjectType1(10002l, "XXX", "YYYY");
        list1.add(type1Obj2);

        ObjectType1 type1Obj3 = new ObjectType1(10003l, "XXX", "YYYY");
        list1.add(type1Obj3);

        ObjectType1 type1Obj4 = new ObjectType1(10004l, "XXX", "YYYY");
        list1.add(type1Obj4);

        ObjectType1 type1Obj5 = new ObjectType1(10005l, "XXX", "YYYY");
        list1.add(type1Obj5);

        List<ObjectType2> list2 = new ArrayList<ObjectType2>();

        ObjectType2 type2Obj1 = new ObjectType2(10001l, "XXX", 2000l);
        list2.add(type2Obj1);

        ObjectType2 type2Obj2 = new ObjectType2(10002l, "XXX", 2001l);
        list2.add(type2Obj2);

        ObjectType2 type2Obj3 = new ObjectType2(50002l, "XXX", 2002l);
        list2.add(type2Obj3);

        ObjectType2 type2Obj4 = new ObjectType2(50003l, "XXX", 2003l);
        list2.add(type2Obj4);

        List<ObjectType1> list3 = retainAll(list1, list2);

        for (ObjectType1 objectType : list3) {
            System.out.println(objectType);
        }

    }

    public static List<ObjectType1> retainAll(List<ObjectType1> firstList,  List<ObjectType2> secondList) {

        List<ObjectType1> list3 = new ArrayList<ObjectType1>();

        for (ObjectType1 first : firstList) {
            for (ObjectType2 second : secondList) {
                if (first.getField1().equals(second.getField1())) {
                    list3.add(first);
                    break;
                }

            }

        }

        return list3;

    }

}

在上面两个对象下面的程序中

ObjectType1 type1Obj1 = new ObjectType1(10001l, "XXX", "YYYY");
            list1.add(type1Obj1);

            ObjectType1 type1Obj2 = new ObjectType1(10002l, "XXX", "YYYY");
            list1.add(type1Obj2);

在两个类中都有共同的field1 list3 将只包含 type1 的两个元素。

于 2013-02-13T06:38:15.957 回答
0

正如@Dilum 所写,您可以使用 Google 的 Guava 库。
此外,如果您只有列表,则应Lists.transform改为使用。
此外,如果您使用 Java 8,那么它看起来像:

List<Long> list1field1 =
    Lists.transform(list1, input -> input == null ? null : input.field1);

或者您可以手动执行此操作:

// list1.removeAll(list2);
Set<Long> set = new HashSet<Long>();
for (ObjectType2 o2 : list2) {
    set.add(o2.field1);
}
Iterator<ObjectType1> i = list1.iterator();
while (i.hasNext()) {
    if (set.contains(i.next().field1)) {
        i.remove();
    }
}
于 2014-09-25T13:10:39.253 回答