Java 如何对列表中的元素进行分组<;P>;到地图<;K、 列表<;V>&燃气轮机;在维持秩序的同时?
我有一个GooglePlaceSummary对象列表,这些对象来自GooglePlacesAPI。我想收集和分组他们的谷歌地方ID,但也保留了元素的顺序。我认为有效的方法是:Java 如何对列表中的元素进行分组<;P>;到地图<;K、 列表<;V>&燃气轮机;在维持秩序的同时?,java,java-8,java-stream,linkedhashmap,collectors,Java,Java 8,Java Stream,Linkedhashmap,Collectors,我有一个GooglePlaceSummary对象列表,这些对象来自GooglePlacesAPI。我想收集和分组他们的谷歌地方ID,但也保留了元素的顺序。我认为有效的方法是: Map<String, List<PlaceSummary>> placesGroupedByPlaceId = places.stream() .collect(Collectors.groupingBy(
Map<String, List<PlaceSummary>> placesGroupedByPlaceId =
places.stream()
.collect(Collectors.groupingBy(
PlaceSummary::getPlaceId,
LinkedHashMap::new,
Collectors.mapping(PlaceSummary::getPlaceId, toList())
));
Map placesGroupedByPlaceId=
places.stream()
.collect(收集器.groupingBy(
PlaceSummary::getPlaceId,
LinkedHashMap::新建,
Collectors.mapping(PlaceSummary::getPlaceId,toList())
));
但它甚至不会编译。看起来应该是这样的
以前我有这样的代码:
Map<String, List<PlaceSummary>> placesGroupedByPlaceId = places.stream()
.collect(Collectors.groupingBy(PlaceSummary::getPlaceId));
Map placesGroupedByPlaceId=places.stream()
.collect(Collectors.groupingBy(PlaceSummary::getPlaceId));
但是,Streams API上的标准.collect()
并没有保留后续HashMap
中元素的顺序(显然,因为HashMap
是无序的)。我希望输出是一个LinkedHashMap
,这样映射就可以按照每个bucket的插入顺序进行排序
但是,我建议的解决方案无法编译。首先,它不能识别PlaceSummary::getPlaceId
,因为它说它不是函数——尽管我知道它是函数。其次,它说我不能将LinkedHashMap
转换为M。M应该是一个通用集合,所以应该被接受
如何使用Java Stream API将列表转换为LinkedHashMap
?有没有简洁的方法?如果它太难理解,我可能会求助于老式的Java8之前的方法
我注意到有,但这并没有我想要的解决方案,因为我需要收集“this”我特别迭代的对象。你真的很接近你想要的:
Map<String, List<PlaceSummary>> placesGroupedByPlaceId =
places.stream()
.collect(Collectors.groupingBy(
PlaceSummary::getPlaceId,
LinkedHashMap::new,
Collectors.mapping(Function.identity(), Collectors.toList())
));
然后像这样使用它:
Map<String, List<PlaceSummary>> placesGroupedById = groupByOrdered(places, PlaceSummary::getPlaceId);
Map placesGroupedById=groupByOrdered(places,PlaceSummary::getPlaceId);
我想你对最终的收集者有些困惑。它仅表示每个映射值中需要的内容。不需要辅助映射收集器,因为您只需要原始对象的列表
Map<String, List<PlaceSummary>> placesGroupedByPlaceId =
places.stream()
.collect(Collectors.groupingBy(PlaceSummary::getPlaceId,
LinkedHashMap::new,
Collectors.toList()));
Map placesGroupedByPlaceId=
places.stream()
.collect(收集器).groupingBy(PlaceSummary::getPlaceId、,
LinkedHashMap::新建,
收藏家;
/**
*我已经编写了更通用的代码,如果您愿意,可以基于任意*
*通过传递方法引用来传递实例变量、id、名称等。
**/
班级学生{
私有int-id;
私有字符串名称;
公立学生(int-id,字符串名){this.id=id;this.name=name;}
/**
*@返回id
*/
public int getId(){return id;}
/**
*@param-id
*要设置的id
*/
public void setId(int id){this.id=id;}
/**
*@返回名称
*/
公共字符串getName(){return name;}
/**
*@param name
*要设置的名称
*/
public void setName(字符串名){this.name=name;}
}
公立班学生{
公共静态void main(字符串[]args){
列表=新的ArrayList();
列表。添加(新学生(1,“Amit”);
增加(新学生(2名,“Sumit”);
增加(新学生(1名,“Ram”);
增加(新学生(2名,“Shyam”);
列表。添加(新学生(3,“Amit”);
列表。添加(新学生(4名,“Pankaj”);
Map如果您需要在保持顺序的同时进行分组并应用一个函数(减少),我可能会使用类似的方法
final Map<Integer,Long>map=stream.collect(Collectors.groupingBy(function
,LinkedHashMap::new
,Collectors.collectingAndThen(Collectors.counting(),Function.identity()))
)
final Mapmap=stream.collect(收集器.groupingBy(函数
,LinkedHashMap::新建
,Collectors.collectingAndThen(Collectors.counting(),Function.identity())
)
从中给出的示例来看,它应该编译。可能是Collectors.toList()
而不是toList()
,除非您静态导入?@njzk2我不认为toList是问题所在-正如您所说,它是静态导入的。LinkedHashMap::新行在IntelliJ中有以下错误:方法引用中的返回类型错误:无法将java.util.LinkedHashMap转换为mt映射收集器应用于值,因此您需要p->p instead地点摘要::getPlaceId@AlexisC.那就是p->p.getPlaceId?那么…这是否意味着我可以用p->p来指代“this”元素?No p->p.getPlaceId意味着PlaceSummary分组的值将由它们的位置id映射。如果您想要实例本身,只需应用identity函数,因此p->p。是的,我认为这让我有点困惑。我认为最好使用参数orders键、值映射、toList()如果我是诚实的-但有点抱怨。我会记住这一点以备将来参考…谢谢。在生产代码中试用过-工作起来像做梦一样谢谢。肯定是对API的误解。此外,我更喜欢placeSummary->placeSummary而不是Function.identity()因为澄清起来似乎更清晰一些。如果您理解代码的目的,那么代码就不太复杂了。我试图做的是将重复ID分组,然后使用规则过滤掉重复的ID。其中一个规则是根据是否是扩展位置保留一个重复的ID(我们增加了位置,为他们提供谷歌API不知道的额外信息)或者不知道。非常感谢
/**
* I have written this code more generic, if you want then you can group based on any *
* instance variable , id, name etc via passing method reference.
**/
class Student {
private int id;
private String name;
public Student(int id, String name) {this.id = id;this.name = name;}
/**
* @return the id
*/
public int getId() {return id;}
/**
* @param id
* the id to set
*/
public void setId(int id) {this.id = id;}
/**
* @return the name
*/
public String getName() {return name;}
/**
* @param name
* the name to set
*/
public void setName(String name) {this.name = name;}
}
public class StudentMain {
public static void main(String[] args) {
List<Student> list = new ArrayList<>();
list.add(new Student(1, "Amit"));
list.add(new Student(2, "Sumit"));
list.add(new Student(1, "Ram"));
list.add(new Student(2, "Shyam"));
list.add(new Student(3, "Amit"));
list.add(new Student(4, "Pankaj"));
Map<?, List<Student>> studentById = groupByStudentId(list,
Student::getId);
System.out.println(studentById);
Map<?, List<Student>> studentByName = groupByStudentId(list,
Student::getName);
System.out.println(studentByName);
}
private static <K, V> Map<?, List<V>> groupByStudentId(List<V> list,
Function<V, K> keyFunction) {
return list.stream().collect(
Collectors.groupingBy(keyFunction, HashMap::new,
Collectors.toList()));
}
}
final Map<Integer,Long>map=stream.collect(Collectors.groupingBy(function
,LinkedHashMap::new
,Collectors.collectingAndThen(Collectors.counting(),Function.identity()))
)