1

我自动生成的 JAXB 类

public class Employee {
   private int id;
   private String name;
   private String department;

   /* Getters and Setters */

}

Employee emp1 = new Employee();
emp1.setId(1);
emp1.setName("A");
emp1.setDepartment("D1");


Employee emp2 = new Employee();
emp2.setId(2);
emp2.setName("B");
emp2.setDepartment("D1");

List<Employee> empList1 = new ArrayList<Employee>();
empList1.add(emp1);
empList2.add(emp2);

Employee emp3 = new Employee();
emp2.setId(3);
emp2.setName("A");
emp2.setDepartment("D1");

List<Employee> empList2 = new ArrayList<Employee>();
empList2.add(emp3);

我想比较列表 empList1 和 empList2 并获得与 Employee 对象的名称和部门字段匹配的结果列表。

基本上,我需要基于两个对象中字段的自定义比较来交叉两个列表。

我正在查看 Google Guava 和 lambdaJ,但我无法找到通过自定义比较逻辑进行交集的解决方案/示例。

任何想法都会有所帮助。

4

3 回答 3

2

为了进行比较,您可以使用 Guava Ordering 或 Java Comparator。对于过滤,您可以使用谓词。

如果您想要通用的东西,您可以使用制作一个比较器(用于 DEP 和 NAME)

    class MyComparator implements Comparator<Employee> {

        @Override
        public int compare(final Employee left, final Employee right) {
            return ComparisonChain.start().compare(left.getName(), right.getName())
                                  .compare(left.getDepartment(), right.getDepartment()).result();
        }

    }

    class MyPredicate implements Predicate<Employee> {

        final List<Employee> employees;
        final Comparator<Employee> comparator;

        public MyPredicate(final List<Employee> employees, final Comparator<Employee> comparator) {
            this.employees = employees;
            this.comparator = comparator;
        }

        @Override
        public boolean apply(@Nullable final Employee input) {
            for (final Employee e : employees) {
                if (comparator.compare(e, input) == 0) {
                    return true;
                }

            }

            return false;
        }

    }

然后你可以像这样使用它:

    final MyComparator comparator = new MyComparator();
    final MyPredicate predicate1 = new MyPredicate(empList1, comparator);
    final MyPredicate predicate2 = new MyPredicate(empList2, comparator);
    System.out.println("####");
    System.out.println(Collections2.filter(empList2, predicate1));
    System.out.println(Collections2.filter(empList1, predicate2));
于 2013-08-08T15:42:01.383 回答
0

手动破解与两个列表相交的方法将是最快的方法。但是,如果您需要更通用的方法来处理其他事情Employee,例如,您可以使用番石榴Equivalence类。有了它,您可以将列表中的条目映射到一个Equivalence.WrapperSets.intersect在这些包装器集上使用。

public static <T> Set<T> intersect(Iterable<? extends T> a, Iterable<? extends T> b, Equivalence<? super T> eq) {
    Function<T, Wrapper<T>> f = wrappingFunction(eq);

    Set<Wrapper<T>> as = ImmutableSet.copyOf(Iterables.transform(a, f));
    Set<Wrapper<T>> bs = ImmutableSet.copyOf(Iterables.transform(b, f));

    SetView<Wrapper<T>> intersection = Sets.intersection(as, bs);

    return ImmutableSet.copyOf(Iterables.transform(intersection,
            Test.<T> unwrappingFunction()));
}

哪里wrappingFunction()unwrappingFunction()两个效用函数:

    public static <T> Function<T, Wrapper<T>> wrappingFunction(
        final Equivalence<? super T> eq) {
    return new Function<T, Wrapper<T>>() {
        public Wrapper<T> apply(T input) {
            return eq.wrap(input);
        }
    };
}

private static final Function<Wrapper<Object>, Object>  UNWRAPPING_FUNCTION = new Function<Wrapper<Object>, Object>() {

    public Object apply(Wrapper<Object> input) {
        return checkNotNull(input).get();
    }
};

@SuppressWarnings("unchecked")
public static <T> Function<Wrapper<T>, T> unwrappingFunction() {
    return ((Function<Wrapper<T>, T>) ((Function<?, ?>) UNWRAPPING_FUNCTION));
}

有了这个,你将不得不实施并Equivalence申请Employeeintersect

Set<Employee> x = intersect(a, b, new Equivalence<Employee>() {

        @Override
        protected boolean doEquivalent(Employee a, Employee b) {
            checkNotNull(a);
            checkNotNull(b);
            return Objects.equals(a.getId(), b.getId())
                && Objects.equals(a.getDepartment(), b.getDepartment())
                && Objects.equals(a.getName(), b.getName());
        }

        @Override
        protected int doHash(Employee t) {
            return t.getId();
        }
    });

在此示例中,返回的Set将不包含重复Employees

于 2013-09-29T13:20:18.460 回答
0
public List<Employee> findIntersections(List<Employee> listA, List<Employee> listB)
{

    List<Employee> returnList = new List<Employee>();
    Employee empA, empB;

    for(int i = 0; i<listA.size; i++)
    {
        for(int j = 0; j<listB.size; j++)
        {
            empA = listA.get(i);
            empB = listB.get(j);

            if(empA.getID == empB.getID() && empA.getName().equals(empB.getName()) && empA.getDepartment().equals(empB.getDepartment()))
            {
                returnList.add(empA);//or add empB...since theyre the same
            }
        }
    }

    return returnList;
}

我想要一个通用的实现。有很多 JAXB 对象需要基于字段进行相等检查。是否有类似于 Comparator 的具有返回布尔值的方法?

这是我发现的(您可能需要一个插件):

不幸的是,jaxb 并没有开箱即用地提供这个。您可以使用此插件,或编写自己的插件以获得更多可定制的行为。

资源:

https://stackoverflow.com/a/7771776/2498729

于 2013-08-07T15:49:17.680 回答