【问题标题】:How to find the duplicate elements without override equals如何在没有覆盖等于的情况下找到重复元素
【发布时间】:2017-12-14 22:52:03
【问题描述】:

我有一个 A 类列表

public class A {
    String port;
    String ip;
    String name;
    Obeject ...others;
}

在这个列表中,我想找到共享相同 ip 和端口的重复元素。

  1. 重写 equals() 来比较 ip 和 port 并使用 hashSet 可能是解决这个问题的一种方法。但我认为 equals() 不应该被覆盖,因为这个类中还有其他字段,它可能会混淆逻辑。

  2. 使用 TreeSet 并实现 Comparator 是另一种方式。但是 ip 和端口很难比较哪个更大,因为我们有 ipv6、ipv4、ip 范围、端口范围等。在 compare() 中,如果只在 ip 和端口相等时返回 0,如果它们不相等则返回 1 将导致逻辑错误。因为TreeSet是通过红黑树实现的。

  3. 一个名为 AHelper 的子类可以使用重写 equals()。但我认为这很愚蠢。

还有其他方法可以解决这个问题吗? ~~~非常感谢。

【问题讨论】:

  • 选项 2 在我看来不错,据我所知,无法避免比较 IP 和端口。
  • 覆盖equals 来简单地比较两个属性不是一个好的选择——我会从一个实用方法开始,它接受A 的实例并比较它们的属性并返回true 或@ 987654325@。我什至会考虑制作一个Equatable 接口,它可以在比较两个对象时为您提供更大的灵活性,因此您可以轻松更改进行比较的方式

标签: java duplicates set treeset


【解决方案1】:

声明一个仅包含 ipport 字段的新类 IpAndPort,并覆盖该类上的 equals(),以便比较这两个字段。定义一个Map,其键为IpAndPort,其值为AList<A>,具体取决于您的需要。遍历List<A>,并为每个元素创建IpAndPort。现在将其添加到以IpAndPort 为键的映射中,或者(1)将A 作为值添加到映射中;或 (2) 为 List<A> 中的每个键收集映射中的所有 A。或者别的什么(你可以把它设为Map<IpAndPort, Integer>,然后只计算每个 IP/端口键的值的数量)。

您还可以通过将IpAndPort 对象作为A 中的实例变量来消除一点冗余,替换ipport 变量。

【讨论】:

  • 方法 3 在我听来就像定义 A 的子类,而此解决方案定义了一个单独的类来仅保存关键信息。
【解决方案2】:

我认为选项 2 是最好的选择,因为比较器的工作是引入排序的外部因素。既然你提到 IP 很难比较,为什么不将 IPv4 和 IPv6 作为单独的属性。得到什么样的数据必须控制填充在对象中的内容。就像说我如何将我的全名与我的昵称进行比较。我认为主要问题是没有通用的比较规则。您比较什么以及如何比较是您将拥有的东西作为设计师/开发人员提出来

【讨论】:

    【解决方案3】:

    在 java 8 中,您可以使用 Predicate 过滤 List 中的元素:

    ArrayList<A> list1 = new ArrayList<>();
            ArrayList<A> list2 = new ArrayList<>();
    
            Stream<A> stream = list1.stream();
            for (A a2 : list2) {
                stream.filter(a1 -> a1.getIp().equals(a2.getIp()) && a1.getPort().equals(a2.getPort()));
            }
    

    list1 将只保留对象A,其ipportlist2 中的相同。

    【讨论】:

    • 是 O(n2) 吗?我觉得跟双循环没什么区别。
    猜你喜欢
    • 2013-05-18
    • 1970-01-01
    • 2019-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-01
    • 2014-01-20
    相关资源
    最近更新 更多