others - lambda - Java 8:如何将String转换为Map<String,List<String>>

我有一个像这样的字符串列表:


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



我想把它转换成 Map<String, List<String>>像这样:


AU = [5631]


CA = [1326]


US = [5423, 6321]



我已经尝试过这个代码,但是我必须创建一个新的类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;


 }


}



但是我想知道,有没有办法将String转换为,Map<String, List<String>>不引入新类。

时间:

你可以这样做:


Map<String, List<String>> locationMap = locations.stream()


 .map(s -> s.split(":"))


 .collect(Collectors.groupingBy(a -> a[0],


 Collectors.mapping(a -> a[1], Collectors.toList())));



一个更好的方法是


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())));



可以进一步简化为


Map<String, List<String>> locationMap = locations.stream().map(DELIMITER::split)


 .collect(Collectors.groupingBy(a -> a[0], 


 Collectors.mapping(a -> a[1], Collectors.toList())));



试试这个


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())));



只要把第一组作为键,第二个组作为值而不是第一个,就可以将代码放在组合中,


Map<String, List<String>> locationMap = locations


 .stream()


 .map(s -> s.split(":"))


 .collect( Collectors.groupingBy( s -> s[0], Collectors.mapping( s-> s[1], Collectors.toList() ) ) );




public static Map<String, Set<String>> groupByCountry(List<String> locations) {


 Map<String, Set<String>> map = new HashMap<>();



 locations.forEach(location -> {


 int pos = location.indexOf(\':\');


 map.compute(location.substring(0, pos), (country, codes) -> {


 codes = codes == null ? new HashSet<>() : codes;


 codes.add(location.substring(pos + 1));


 return codes;


 });


 });



 return map;


}



你的map location 需要根据键排序,你可以尝试以下操作,


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]}



...