【问题标题】:Java8 Streams - Remove Duplicates With Stream DistinctJava 8 Stream - 使用 Stream Distinct 删除重复项
【发布时间】:2015-01-12 21:55:35
【问题描述】:

我有一个流,例如:

Arrays.stream(new String[]{"matt", "jason", "michael"});

我想删除以相同字母开头的名称,以便只剩下一个以该字母开头的名称(不管是哪个)。

我试图了解distinct() 方法的工作原理。我在文档中读到它基于对象的“equals”方法。但是,当我尝试包装 String 时,我注意到 equals 方法从未被调用,并且没有任何内容被删除。我这里有什么遗漏吗?

包装类:

static class Wrp {
    String test;
    Wrp(String s){
        this.test = s;
    }
    @Override
    public boolean equals(Object other){
        return this.test.charAt(0) == ((Wrp) other).test.charAt(0);
    }
}

还有一些简单的代码:

public static void main(String[] args) {
    Arrays.stream(new String[]{"matt", "jason", "michael"})
    .map(Wrp::new)
    .distinct()
    .map(wrp -> wrp.test)
    .forEach(System.out::println);
}

【问题讨论】:

  • 这是我在this answer 中描述的技术。 (滚动到答案的末尾)。这会让你做filter(distinctByKey(s -> s.charAt(0)))
  • 旁注:对于文字流,使用Stream.of("matt", "jason", "michael") 通常更容易。

标签: java string java-8 java-stream


【解决方案1】:

每当你重写equals时,你还需要重写hashCode()方法,该方法将在distinct()的实现中使用。

在这种情况下,您可以使用

@Override public int hashCode() {
   return test.charAt(0);
}

...这样就可以了。

【讨论】:

  • 是的,这似乎有效。如果您可以将比较器传递给distinct 以使这更容易一些,那就太好了。
  • 如果这是你想要的,你可以把它转储到TreeSet
  • 你是对的......有时当你拿到一把新锤子时,一切都开始看起来像钉子。 ;-)
【解决方案2】:

替代方法

    String[] array = {"matt", "jason", "michael"};
    Arrays.stream(array)
            .map(name-> name.charAt(0))
            .distinct()
            .map(ch -> Arrays.stream(array).filter(name->name.charAt(0) == ch).findAny().get())
            .forEach(System.out::println);

【讨论】:

    猜你喜欢
    • 2022-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-17
    • 1970-01-01
    • 2018-05-17
    相关资源
    最近更新 更多