【问题标题】:How to work with Set Differences in Java using objects?如何使用对象在 Java 中设置差异?
【发布时间】:2020-01-23 20:05:48
【问题描述】:

我需要获得两个集合/列表之间的集合差异,但这些集合中的对象构造不同。我想只在这些对象的一个​​字段上计算集合差异,我该怎么做?

POJO o1 = new POJO();
o1.setName("Bean");
o1.setLocation("Boston");

POJO o2 = new POJO();
o2.setName("Bagel");
o2.setLocation("NYC");

POJO o3 = new POJO();
o3.setName("Bean");

List<POJO> p1 = new ArrayList<>();
p1.add(o1);
p1.add(o2);

List<POJO> p2 = new ArrayList<>();
p2.add(o3);

Collection<POJO> subList = CollectionUtils.subtract(p1, p2);
System.out.println("subList: "+subList.toString());

我看到的输出是:subList: [POJO(name=Bean)],即o3。但是对于我的用例,o1o3 是相同的 - 我该如何实现呢?我也覆盖了默认的equals() 方法,但我认为它没有被调用。

【问题讨论】:

  • 我不得不搜索一下CollectonUtils 的来源。它似乎来自Apache。重载版本将谓词作为第三个参数来确定要减去的值。请更新您的标签以包含适当的第三方 API 参考。

标签: java collections set


【解决方案1】:

您可以使用来自Eclipse CollectionsUnifiedSetWithHashingStrategy

POJO o1 = new POJO();
o1.setName("Bean");
o1.setLocation("Boston");

POJO o2 = new POJO();
o2.setName("Bagel");
o2.setLocation("NYC");

POJO o3 = new POJO();
o3.setName("Bean");

HashingStrategy<POJO> strategy = HashingStrategies.fromFunction(POJO::getName);

MutableSet<POJO> set1 =
        HashingStrategySets.mutable.with(strategy, o1, o2);
MutableSet<POJO> set2 =
        HashingStrategySets.mutable.with(strategy, o3);
MutableSet<POJO> difference = set1.difference(set2);

Assert.assertEquals("[POJO(name=Bagel)]", difference.toString());

This answer 更详细地解释了UnifiedSetWithHashingStrategy 的工作原理。

注意:我是 Eclipse Collections 的提交者。

【讨论】:

    【解决方案2】:

    您可以借助重载的subtract with predicate 来实现这一点。

    1. POJO 类中覆盖 hashcodeequals,(以及 toString 以获得干净的输出)

      @Override
      public boolean equals(Object o) {
          if (this == o) return true;
          if (o == null || getClass() != o.getClass()) return false;
          POJO pojo = (POJO) o;
          return Objects.equals(name, pojo.name);
      }
      
      @Override
      public int hashCode() {
          return name.hashCode();
      }
      
    2. 将谓词与 set as 一起使用

      Collection<POJO> subList = CollectionUtils.subtract(p1, p2, new Predicate<POJO>() {
          @Override
          public boolean evaluate(POJO object) {
              return p1.contains(object); // might need to make p1 final
          }
      });
      

    结果:

    子列表:[百吉饼]

    注意:Apache common 不支持Java 8 BiPredicate

    【讨论】:

    • 这太不可思议了!我不知道我们可以覆盖 subtract 方法中的谓词。非常感谢!
    • 我很高兴能帮上忙,编码快乐 :)
    猜你喜欢
    • 1970-01-01
    • 2019-06-08
    • 2021-06-14
    • 1970-01-01
    • 1970-01-01
    • 2022-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多