Потоки Java8 - удаление дубликатов с помощью Stream Distinct
У меня есть поток, например:
Arrays.stream(new String[]{"matt", "jason", "michael"});
Я хотел бы удалить имена, начинающиеся с того же письма, чтобы осталось только одно имя (не имеет значения, какое), начиная с этой буквы.
Я пытаюсь понять, как работает метод distinct()
. Я прочитал в документации, что он основан на методе "равно" объекта. Однако, когда я пытаюсь обернуть String, я замечаю, что метод equals никогда не вызывается и ничего не удаляется. Здесь что-то не хватает?
Класс Wrapper:
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);
}
Ответы
Ответ 1
Всякий раз, когда вы переопределяете equals
, вам также необходимо переопределить метод hashCode()
, который будет использоваться в реализации distinct()
.
В этом случае вы можете просто использовать
@Override public int hashCode() {
return test.charAt(0);
}
..., который будет работать нормально.
Ответ 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);