Dividir las teclas de un mapa y crear un nuevo mapa con las nuevas claves y los valores asociados

John Stef:

Tengo un Listde Objectsque cada uno de ellos contiene una X, el valor de Y ( Doubles) y un nombre String. Como tengo varias entradas de los mismos nombres que se corresponden con las coordenadas, quiero enlazar todos los nombres de todas las coordenadas, que me las arreglé para hacerlo mediante la creación de un Maptipo de<String, List<Object>>

Ejemplo de salida:

One             [[0.1,0.1,0.1],[0.2,0.3,0.4]]
One,Two         [[0.1,0.1]    ,[0.4,0.5]]         
One,Two,Three   [[0.1,0.1]    ,[0.6,0.7]]

Lo que quiero hacer ahora es dividir los nombres donde hay una coma ,y lograr el resultado siguiente:

One   [[0.1,0.1,0.1,0.1,0.1,0.1],[0.2,0.3,0.4,0.5,0.6,0.7]]
Two   [[0.01,0.01,0.01,0.01]    ,[0.4,0.5,0.6,0.7]]                    
Three [[0.01,0.01]              ,[0.6,0.7]]

Mi código que funciona es:

Map<String, List<Coordinates>> newList = coordinateList.stream()
                .collect(Collectors.groupingBy(Coordinates::getName));

que crea la primera Map.

Con el fin de hacer la segunda parte he intentado lo siguiente junto con varias combinaciones, pero sin suerte:

newList.entrySet().stream()
        .flatMap(entry -> Arrays.stream(entry.getKey().split(","))
                .map(s -> new AbstractMap.SimpleEntry<>(s, entry.getValue())))
        .collect(Collectors.groupingBy(Map.Entry::getKey, 
                Collectors.flatMapping(entry -> entry.getValue().stream(), Collectors.toList())));

El error que consigo es:

The method flatMapping((<no type> entry) -> {}, Collectors.toList()) is undefined for the type Collectors

Tenga en cuenta que al cambiar flatMappinga mappinglas obras pero no resuelve el problema.

Otra variación del código que he intentado es:

Map<String, List<Object>> collect1 = map.entrySet().stream()
        .flatMap(entry -> Arrays.stream(entry.getKey().split(","))
                .map(s -> new AbstractMap.SimpleEntry<>(s, entry.getValue())))
        .collect(groupingBy(Map.Entry::getKey, mapping(Map.Entry::getValue, toList())))
        .entrySet().stream()
        .flatMap(entry -> entry.getValue().stream()
                .flatMap(Collection::stream)
                .map(o -> new AbstractMap.SimpleEntry<>(entry.getKey(), o)))
        .collect(groupingBy(Map.Entry::getKey, mapping(Map.Entry::getValue, toList())));

Todavía no hay suerte y yo regularmente obtener el error Cannot infer type argument(s) for <R> flatMap(Function<? super T,? extends Stream<? extends R>>)

¿Algunas ideas?

Ravindra Ranwala:

Parece que no está utilizando java9. Si está utilizando Java9 el primer enfoque con Collectors.flatMappingel trabajo lo haría. Pero todavía no veo ningún punto en la creación de una nueva Map.Entryaquí. Echar un vistazo a esta solución.

private static final Pattern COMMA_DELIMITER = Pattern.compile(",\\s*");

Map<String, Set<Coordinate>> nameToCoordinates = coordinates.stream()
    .flatMap(
        c -> COMMA_DELIMITER.splitAsStream(c.getName())
            .map(n -> new Coordinate(n, c.getX(), c.getY())))
    .collect(Collectors.groupingBy(Coordinate::getName, Collectors.toSet()));

Para cada coordenada, agarrar de su nombre, que se dividió con el, y luego delimitador para cada una de dichas nombre del token crear una nueva coordenada con ese nuevo nombre y coordenadas x, y. Entonces simplemente recogerla mediante el colector groupingBy. Ya que se necesita para mantener los valores de coordenadas única distintos, hay que anular iguales y métodos hashCode en la clase de coordenadas. Así es como se ve.

@Override
public int hashCode() {
    int result = name.hashCode();
    result = 31 * result + Double.hashCode(x);
    result = 31 * result + Double.hashCode(y);
    return result;
}

@Override
public boolean equals(Object obj) {
    return obj instanceof Coordinate && ((Coordinate) obj).getX() == x 
        && ((Coordinate) obj).getY() == y
        && ((Coordinate) obj).getName().equals(name);
}

Por alguna razón, si realmente necesita usar el mapa intermediaria creada en el primer paso, a continuación, la solución sería así.

newList.values().stream().flatMap(Collection::stream)
    .flatMap(
        c -> COMMA_DELIMITER.splitAsStream(c.getName())
            .map(n -> new Coordinate(n, c.getX(), c.getY())))
    .collect(Collectors.groupingBy(Coordinate::getName, Collectors.toSet()));

Aquí está la salida.

{Uno = [[name = Uno, x = 0,1, y = 0,2], [name = Uno, x = 0,1, y = 0,4], [name = Uno, x = 0,1, y = 0,3], [name = Uno , x = 0,1, y = 0,5], [name = Uno, x = 0,1, y = 0,6], [name = Uno, x = 0,1, y = 0,7]], Two = [[name = Dos, x = 0,1 , y = 0,4], [name = Dos, x = 0,1, y = 0,5], [name = Dos, x = 0,1, y = 0,6], [name = Dos, x = 0,1, y = 0,7]], Three = [[name = Tres, x = 0,1, y = 0,6], [name = Tres, x = 0,1, y = 0,7]]}

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=204951&siteId=1
Recomendado
Clasificación