按映射的java列表中的动态列数分组

按映射的java列表中的动态列数分组,java,group-by,java-stream,Java,Group By,Java Stream,我有以下aList对象: List<Map<String,String>> aList = new ArrayList<>(); Map<String,String> mapOne= new HashMap<>(); Map<String,String> mapTwo= new HashMap<>(); mapOne.put("Name","John"); mapOne.p

我有以下
aList
对象:

    List<Map<String,String>> aList = new ArrayList<>();
    Map<String,String> mapOne= new HashMap<>();
    Map<String,String> mapTwo= new HashMap<>();
    mapOne.put("Name","John");
    mapOne.put("Age","30");
    mapOne.put("City","Kolkata");
    mapTwo.put("Name","Jack");
    mapTwo.put("Age","31");
    mapTwo.put("City","Kolkata");
    aList.add(mapOne);
    aList.add(mapTwo);

但正如您所注意到的,这里我只能按
城市
分组,但用户应该可以选择按其他属性分组,如
姓名
年龄
等。因此,当我不知道用户将根据哪些属性和多少属性进行分组时,如何返回结果?

当存在多个条件时,您似乎希望返回一个
映射

您可以使用
groupingBy
分类器返回带有所需字段值的映射,然后根据该列表进行分组

Map<List<String>, List<Collection<String>>> city = aList.stream()
        .collect(Collectors.groupingBy(map -> List.of(map.get("City"), map.get("Age")),
                Collectors.mapping(Map::values, Collectors.toList())));
System.out.println(city);
如果您使用的是Java<9,请将(..)列表替换为
Arrays.asList(..)

为了使其动态化,您可以将构建分类器函数的逻辑移动到一个方法中,并为每个映射调用它

private static List<String> buildClassificationFunction(Map<String,String> map, List<String> fields) {
    return fields.stream()
            .map(map::get)
            .collect(Collectors.toList());
}

List<String> fields = List.of("City", "Age"); //This will be constructed as per user's wish

Map<List<String>, List<Collection<String>>> city = aList.stream()
        .collect(Collectors.groupingBy(map -> 
                    buildClassificationFunction(map, fields), //Call the function to build the list
                Collectors.mapping(Map::values, Collectors.toList())));
私有静态列表buildClassificationFunction(映射、列表字段){
返回字段。stream()
.map(map::get)
.collect(Collectors.toList());
}
列表字段=列表(“城市”、“年龄”)//这将根据用户的意愿进行构建
Map city=aList.stream()
.collect(收集器)。分组方式(地图->
buildClassificationFunction(映射,字段),//调用该函数以生成列表
Collectors.mapping(Map::values,Collectors.toList());

当存在多个条件时,似乎要返回一个
映射

您可以使用
groupingBy
分类器返回带有所需字段值的映射,然后根据该列表进行分组

Map<List<String>, List<Collection<String>>> city = aList.stream()
        .collect(Collectors.groupingBy(map -> List.of(map.get("City"), map.get("Age")),
                Collectors.mapping(Map::values, Collectors.toList())));
System.out.println(city);
如果您使用的是Java<9,请将(..)列表替换为
Arrays.asList(..)

为了使其动态化,您可以将构建分类器函数的逻辑移动到一个方法中,并为每个映射调用它

private static List<String> buildClassificationFunction(Map<String,String> map, List<String> fields) {
    return fields.stream()
            .map(map::get)
            .collect(Collectors.toList());
}

List<String> fields = List.of("City", "Age"); //This will be constructed as per user's wish

Map<List<String>, List<Collection<String>>> city = aList.stream()
        .collect(Collectors.groupingBy(map -> 
                    buildClassificationFunction(map, fields), //Call the function to build the list
                Collectors.mapping(Map::values, Collectors.toList())));
私有静态列表buildClassificationFunction(映射、列表字段){
返回字段。stream()
.map(map::get)
.collect(Collectors.toList());
}
列表字段=列表(“城市”、“年龄”)//这将根据用户的意愿进行构建
Map city=aList.stream()
.collect(收集器)。分组方式(地图->
buildClassificationFunction(映射,字段),//调用该函数以生成列表
Collectors.mapping(Map::values,Collectors.toList());

@user7,是的,我理解,但问题是它可能只是
城市
,或者是
城市
名称
的组合……这怎么可能是组合呢?在这种情况下,是否要返回两个
Map
?@user7我只需要Map,我将在前端为用户打印值。关键可以是用户选择的组合,因此它当然应该更改为
Map
您可以展示一个例子,说明多个标准的结果是什么样子吗?@user7所以现在它的打印方式是
{Kolkata=[[Kolkata,30,John],[Kolkata,31,Jack]}
我在想象多个组,例如城市和年龄,它应该看起来像
{[Kolkata,30]=[[Kolkata,30,John]]}{[Kolkata,31]=[[Kolkata,31,Jack]]}
所以我很抱歉,结果可能会像列表`@user7,是的,我理解,但问题是它可能只是
城市
,或者是
城市
名称
的组合……这怎么可能是组合呢?在这种情况下,是否要返回两个
Map
?@user7我只需要Map,我将在前端为用户打印值。关键可以是用户选择的组合,因此它当然应该更改为
Map
您可以展示一个例子,说明多个标准的结果是什么样子吗?@user7所以现在它的打印方式是
{Kolkata=[[Kolkata,30,John],[Kolkata,31,Jack]}
我在想象多个组,例如城市和年龄,它应该看起来像
{[Kolkata,30]=[[Kolkata,30,John]]}{[Kolkata,31]=[[Kolkata,31,Jack]]}
所以我很抱歉,结果可能会像列表` buildClassificationFunction是我要问的,但你添加了它,完美的答案!buildClassificationFunction是我要问的,但你添加了它,完美的答案!