Biorąc pod uwagę, że wszystkie instancje TypeA w List<TypeA> mają instancję SubTypeB ustawioną w polu superTypeB, muszę odfiltrować zduplikowane instancje TypeA z listy, gdzie duplikat oznacza wartości propertyA i propertyB z SubTypeB są zgodne. Czy można to zrobić za pomocą interfejsu API strumieniowego Java 8?

public class TypeA {
  private SuperTypeB superTypeB;
  public SuperTypeB getSuperTypeB(){ return superTypeB; }
}

public class SuperTypeB {
  private String propertyX;
}

public class SubTypeB extends SuperTypeB {
  private String propertyA;
  private String propertyB;
  public String getPropertyA(){ return propertyA; }
  public String getPropertyB(){ return propertyB; }
}
1
skidalgo 19 marzec 2020, 23:50

2 odpowiedzi

Najlepsza odpowiedź

Musisz się upewnić, że nie map przed filter zbieraniem tego samego typu. Korzystając z distinctByKey narzędzia, możesz dodatkowo collect przejść do List tak jak :

List<TypeA> filteredTypeAs = typeAList.stream()
        .filter(distinctByKey(s -> {
            SubTypeB subTypeB = (SubTypeB) s.getSuperTypeB();
            return Arrays.asList(subTypeB.getPropertyA(), subTypeB.getPropertyB());
        }))
        .collect(Collectors.toList());

Uwaga : opiera się to na założeniu, jak podano w pytaniu, że wszystkie podtypy można rzutować bez czeku instanceof.

1
Naman 20 marzec 2020, 04:53

Czy możesz override equals i hashCode metodę dla typów TypeA i SubTypeB?

Jeśli tak, jest to dość proste. Jeśli nie, odpowiednio zmodyfikuję tę odpowiedź.

class TypeA {
    private SuperTypeB superTypeB;
    public SuperTypeB getSuperTypeB(){ return superTypeB; }


        @Override
        public boolean equals( final Object o) {
            if (this == o) return true;
            if (!(o instanceof TypeA)) return false;
            TypeA typeA = (TypeA) o;
            return superTypeB.equals(typeA.superTypeB);
        }

        @Override
        public int hashCode() {
            return Objects.hash(superTypeB);
        }
    }

    class SubTypeB extends SuperTypeB {
        private String propertyA;
        private String propertyB;
        public String getPropertyA(){ return propertyA; }
        public String getPropertyB(){ return propertyB; }


        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (!(o instanceof SubTypeB)) return false;
            SubTypeB subTypeB = (SubTypeB) o;
            return propertyA.equals(subTypeB.propertyA) &&
                propertyB.equals(subTypeB.propertyB);
        }

        @Override
        public int hashCode() {
            return Objects.hash(propertyA, propertyB);
        }

    }

Następnie wszystko, co musisz zrobić, to:

List<TypeA> finalList = list.stream().distinct().collect(Collectors.toList());

Jedyną gwarancją, jaką możesz uzyskać w interfejsie API strumienia, że otrzymasz pierwsze wystąpienie każdego odrębnego obiektu, jest kolejność, w jakiej strumień emituje obiekty. W przeciwnym razie nie masz kontroli nad tym, który element napotkasz jako pierwszy.

0
Rajan Prasad 20 marzec 2020, 04:42