7

Java:如何使用不同的等于定义执行列表操作?

我有两个通用 POJO 列表。我需要根据比较列表中 POJO 的不同方式对列表执行一些设置操作。

例如,如果我的 POJO 具有以下结构:

public class GenericPojo {
    private String id;
    private String address;
    private String city;
    private String country;
    private String extraDetails;
}

(使用适当的 getter 和 setter)

给定List1<GenericPojo>and List2<GenericPojo>,我将如何找到:

List1 - List2(GenericPojo如果只有 ID 相等,则类相等)

List1 和 List2 的交集(其中id, address, city, country, 但不extraDetails相等GenericPojo

两个不同的自定义比较器类在这里会有所帮助吗?是否有任何库可以有效地处理这些操作,或者我应该尝试实现自己的库?

4

7 回答 7

2

如果您必须控制无法控制的课程,我建议您使用委托。这是我的尝试:

  1. 基于装饰器模式,围绕s创建一个实现合同的RichList<T>包装器。ListList
  2. EqualityChecker<T>使用单一方法`public boolean equal(T t1, T, t2)创建一个接口。
  3. 为您的通用 pojo 实现此接口两次:一次仅检查 ID,另一次检查其他字段。
  4. 添加您感兴趣的两种方法(设置减法和设置交集),但带有一个补充参数,该参数是EqualityChecker<T>将为您进行相等性测试的具体实例。

因此,您可以将这两个操作添加到List您为其编写了EqualityChecker.

进一步改进:您还可以编写一个默认值 EqualityChecker<T>,它只调用比较对象的 equals 方法。然后,您可以重载这两个新操作以默认EqualityChecker.

于 2009-12-06T14:06:42.760 回答
1

如果您的列表不包含重复项(与假设的自定义比较器类相比),您可以使用两个 TreeSet,分别用您的两个比较器实例化。

这样做的一个缺点(除了重复约束)是迭代元素时获得的顺序取决于比较器。

于 2009-12-06T12:57:59.653 回答
1

鉴于您对平等的具体要求,List#removeAll()并且List#retainAll()不符合您的需求,因此我认为您需要一个自定义实现来执行与这两种操作类似的操作。

于 2009-12-06T13:20:50.933 回答
0

没有遵循 List 契约的解决方案,并且现有的 list 实现都不允许您提供比较器。equals(Object)List 契约根据每个元素的方法定义列表的行为。

compare如果比较器的方法与每个元素的方法不一致,那么建议使用带有不同比较器的 TreeSet 也违反了约定equals(Object)

在实践中,您可能需要实现自己的列表类。您可以将其设为不严格遵循 List 协定的 List 实现,但您需要注意这不会破坏其他库方法/类。

于 2009-12-06T13:21:24.150 回答
0

如果您不想自己编写 set 操作并且不介意浪费一些 CPU 和内存资源,您可以:

  • WrappedPojo根据你的 s构造GenericPojos
  • 给出WrappedPojo合适的实现equals()
  • 创建适当类型的新列表WrappedPojo以执行操作
  • 操作完成后将包含的 s复制GenericPojo回其原始容器(如果需要)。

丑陋但简单。

于 2009-12-06T13:30:27.403 回答
0

您可以通过以下方法将所有这些保存在域对象中:

  1. 实施equals(... )onGenericPojo仅基于id
  2. 根据附加字段定义为带有...WrappedPojo的包装器。GenericPojoequals()GenericPojo
  3. 对于第二个用例,使用包装实例列表。

我建议根本问题是试图拥有一个具有不同相等定义的域类。

于 2009-12-06T13:34:43.553 回答
0

您尝试执行的两个操作都是功能性的,尽管 Java 不能很好地支持这些操作,您可能会以非常不同的方式编写它们。您可能必须重新考虑要达到的目标以适应 java。

您正在做的是对数据类型的投影执行操作(即对于一组字段)

您正在使用的操作也是 Set 操作,而不是 List 操作。例如,您不能取两个列表的交集(或者至少您必须定义这意味着什么) Remove 可能不会完全按照您对列表的预期执行。

想象一下,您有一个方法,它只返回您指定的字段的 pojo 集合。过去,我编写了一个库来使用动态生成的类有效地执行此操作,看看函数式 Java 或类似的。

public static <Pojo, Pojo2> Set<Pojo2> project(Collection<Pojo> collection,
      String... fieldsToRetain);

List1 - List2(如果只有 ID 相等,则 GenericPojo 类是相等的)

Set<PojoWithId> setOfIds = project(list1, "id")
setOfIds.retainAll(project(list2, "id"));

List1 和 List2 的交集(其中 id、address、city、country,但不是 GenericPojo 的 extraDetails 相等)

Set<PojoWithThreeFields> intersection = project(list1, "id", "address", "city", "country");
intersection.retainAll(project(list2, "id", "address", "city", "country"));
于 2009-12-06T15:24:24.060 回答