web-dev-qa-db-fra.com

Streams Java8 - Supprimer les doublons avec Stream Distinct

J'ai un flux tel que:

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

Je voudrais supprimer les noms qui commencent par la même lettre afin qu'il ne reste qu'un seul nom (peu importe lequel) commençant par cette lettre.

J'essaie de comprendre comment fonctionne la méthode distinct() . J'ai lu dans la documentation qu'elle est basée sur la méthode "égal" d'un objet. Cependant, lorsque j'essaie d'encapsuler la chaîne, je remarque que la méthode equals n'est jamais appelée et que rien n'est supprimé. Y a-t-il quelque chose qui me manque ici?

Classe 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);
    }
}

Et un code simple:

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);
}
26
Matt Klooster

Chaque fois que vous remplacez equals, vous devez également remplacer la méthode hashCode(), qui sera utilisée dans l'implémentation de distinct().

Dans ce cas, vous pouvez simplement utiliser

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

... ce qui fonctionnerait très bien.

20
Louis Wasserman

Approche alternative

    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);
17
Sujit Kamthe