Tengo una clase

public class A{
   private String x;
   private String y;
   private String z;
}

Tengo varias listas List<List<A>> y necesito encontrar las entradas comunes en todas las listas. Las entradas son las mismas si la x de un objeto == la x de otro objeto.

Si estuviera comprobando la igualdad de los objetos, podría haber convertido las listas en conjuntos y haber utilizado retainAll(). Pero, ¿cómo hago esto cuando y y z podrían ser diferentes? Por x tiene que ser el mismo.

0
Rish 17 oct. 2017 a las 20:20

3 respuestas

La mejor respuesta

En su clase, escriba una función que le devuelva su valor X ...

public class A {
    private String x;
    private String y;
    private String z;
    ...
    public String getX() {
        return x;
    }
}

... luego itere sobre la lista de listas (O (n ^ 2)) y ordénelas según sus valores X comunes.

public Map<String, List<A>> findCommonEntries(List<List<A>> aListList) {
    Map<String, List<A>> aMap = new HashMap<>();

    for (List<A> aList : aListList) {
        for (A a : aList) {
            if (!aMap.containsKey(a.getX()))
                aMap.put(a.getX(), new ArrayList<>());

            aMap.get(a.getX()).add(a);
        }
    }
}

Al final de esto, debe tener un mapa de todas las cadenas almacenadas en cualquier lugar de una X a una lista de todas las A que contienen esa X.

0
KristinaTracer 17 oct. 2017 a las 21:56

Este problema es un buen caso de uso para las secuencias Java8, donde puede aplicar diferentes recopiladores para acumular los elementos de una secuencia. El siguiente código realizará la transformación solicitada:

Map<String, List<A>> collect = lists.stream()
        .flatMap(Collection::stream)
        .collect(Collectors.groupingBy(A::getX));

Esta API definitivamente gana en legibilidad, pero también podría proporcionar un buen rendimiento, ya que JDK proporciona este recopilador.

Puede encontrar un ejemplo de trabajo aquí: https://gist.github.com/sermojohn/e8828288172d5c9b25a4c4 >

2
Yannis Sermetziadis 18 oct. 2017 a las 06:02

Puede aplanar todas las listas en una sola lista, agrupar todos los elementos con el campo x y luego dejar las claves que se presentan en todas las listas (por tamaño de valores):

public static Set<String> getCommonEntries(List<List<A>> lists) {
    Map<String, List<A>> map = lists.stream()
                                    .flatMap(Collection::stream)
                                    .collect(Collectors.groupingBy(A::getX));
    map.values().removeIf(l -> l.size() != lists.size());
    return map.keySet();
}
0
oleg.cherednik 17 oct. 2017 a las 20:21