web-dev-qa-db-fra.com

Java 8: Comment convertir List <String> en Map <String, List <String>>?

J'ai une liste de chaînes comme:

List<String> locations = Arrays.asList("US:5423","US:6321","CA:1326","AU:5631");

Et je veux convertir en Map<String, List<String>> comme:

AU = [5631]
CA = [1326]
US = [5423, 6321]

J'ai essayé ce code et cela fonctionne mais dans ce cas, je dois créer une nouvelle classe GeoLocation.Java.

List<String> locations=Arrays.asList("US:5423", "US:6321", "CA:1326", "AU:5631");
Map<String, List<String>> locationMap = locations
        .stream()
        .map(s -> new GeoLocation(s.split(":")[0], s.split(":")[1]))
        .collect(
                Collectors.groupingBy(GeoLocation::getCountry,
                Collectors.mapping(GeoLocation::getLocation, Collectors.toList()))
        );

locationMap.forEach((key, value) -> System.out.println(key + " = " + value));

GeoLocation.Java

private class GeoLocation {
    private String country;
    private String location;

    public GeoLocation(String country, String location) {
        this.country = country;
        this.location = location;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }
}

Mais je veux savoir, existe-t-il un moyen de convertir List<String> à Map<String, List<String>> sans introduire de nouvelle classe.

17
Vinit Solanki

Vous pouvez le faire comme ceci:

Map<String, List<String>> locationMap = locations.stream()
        .map(s -> s.split(":"))
        .collect(Collectors.groupingBy(a -> a[0],
                Collectors.mapping(a -> a[1], Collectors.toList())));

Une bien meilleure approche serait,

private static final Pattern DELIMITER = Pattern.compile(":");

Map<String, List<String>> locationMap = locations.stream()
    .map(s -> DELIMITER.splitAsStream(s).toArray(String[]::new))
        .collect(Collectors.groupingBy(a -> a[0], 
            Collectors.mapping(a -> a[1], Collectors.toList())));

Mise à jour

Selon le commentaire suivant, cela peut être encore simplifié,

Map<String, List<String>> locationMap = locations.stream().map(DELIMITER::split)
    .collect(Collectors.groupingBy(a -> a[0], 
        Collectors.mapping(a -> a[1], Collectors.toList())));
24
Ravindra Ranwala

Essaye ça

Map<String, List<String>> locationMap = locations.stream()
            .map(s ->  new AbstractMap.SimpleEntry<String,String>(s.split(":")[0], s.split(":")[1]))
            .collect(Collectors.groupingBy(Map.Entry::getKey,
                     Collectors.mapping(Map.Entry::getValue, Collectors.toList())));
3
Hadi J

Vous pouvez simplement mettre le code en regroupement par partie où vous placez le premier groupe comme clé et le second comme valeur au lieu de le mapper en premier

Map<String, List<String>> locationMap = locations
            .stream()
            .map(s -> s.split(":"))
            .collect( Collectors.groupingBy( s -> s[0], Collectors.mapping( s-> s[1], Collectors.toList() ) ) );
3
n1t4chi

Et POJO. Il ne semble pas compliqué de comparer avec les flux.

public static Map<String, Set<String>> groupByCountry(List<String> locations) {
    Map<String, Set<String>> map = new HashMap<>();

    locations.forEach(location -> {
        String[] parts = location.split(":");
        map.compute(parts[0], (country, codes) -> {
            codes = codes == null ? new HashSet<>() : codes;
            codes.add(parts[1]);
            return codes;
        });
    });

    return map;
}
2
oleg.cherednik

Il semble que votre carte de localisation doive être triée en fonction des clés, vous pouvez essayer ce qui suit

List<String> locations = Arrays.asList("US:5423", "US:6321", "CA:1326", "AU:5631");

    Map<String, List<String>> locationMap = locations.stream().map(str -> str.split(":"))
            .collect(() -> new TreeMap<String, List<String>>(), (map, parts) -> {
                if (map.get(parts[0]) == null) {
                    List<String> list = new ArrayList<>();
                    list.add(parts[1]);
                    map.put(parts[0], list);
                } else {
                    map.get(parts[0]).add(parts[1]);
                }
            }, (map1, map2) -> {
                map1.putAll(map2);
            });

    System.out.println(locationMap); // this outputs {AU=[5631], CA=[1326], US=[5423, 6321]}
1
chaitanya89