Java 8嵌套分组
我有两个问题,我似乎无法解决。第一个是我需要一种方式来进行动态嵌套分组,其中可以有1-n个嵌套组,用户可以通过。Java 8嵌套分组
第二个问题是我需要将结果展平concat而不是嵌套。
我的示例输入看起来像这样:
List<Map<String, String>> fakeData = new LinkedList<>();
Map<String, String> data1 = new HashMap<>();
data1.put("ip","10.0.1.0");
data1.put("uid","root");
data1.put("group","admin");
fakeData.add(data1);
Map<String, String> data2 = new HashMap<>();
data2.put("ip","10.0.1.1");
data2.put("uid","tiger");
data2.put("group","user");
fakeData.add(data2);
Map<String, String> data3 = new HashMap<>();
data3.put("ip","10.0.1.1");
data3.put("uid","woods");
data3.put("group","user");
fakeData.add(data3);
最终结果有地图键的的concat:
{
"10.0.1.1user": [
{
"uid": "tiger",
"ip": "10.0.1.1",
"group": "user"
},
{
"uid": "woods",
"ip": "10.0.1.1",
"group": "user"
}
],
"10.0.1.0admin": [
"uid": "root",
"ip": "10.0.1.0",
"group": "admin"
]
}
通知的键的concat而不是映射内嵌套的地图。
我试图创建一个groupingby在那里可以没有任何的运气是动态的:
fakeData.stream()
.collect(groupingBy(map -> map.get("ip"),
groupingBy(map -> map.get("uuid"),
... nested "n" times)));
这是我想要实现的接口:
public Map<String, List<Map<String, String>>> doGrouping(List<String> columns,
List<Map<String, String>> data);
尝试以下操作:
public Map<String, List<Map<String, String>>> doGrouping(
List<String> columns,
List<Map<String, String>> data) {
return data.stream()
.collect(Collectors.groupingBy(
elem -> columns.stream()
.map(elem::get)
.collect(Collectors.joining())));
}
首先,我流了data
,这是地图的列表。我立即使用Collectors.groupingBy
和流的每个元素计算出的一个密钥,将流收集到一个列表映射表中。
计算密钥是棘手的部分。为此,我给出了给定的列表columns
,并且将这些列中的每一列都转换为流的元素的相应值。我通过Stream.map
方法做到这一点,通过elem::map
作为映射函数。最后,我通过使用Collectors.joining
将这个内部流收集到一个单一字符串中,以高效的方式将流的每个元素连接到最终的字符串中。
编辑:如果所有columns
的元素作为data
中的地图元素的键存在,上述代码运行良好。为了更安全的使用以下命令:
return data.stream()
.collect(Collectors.groupingBy(
elem -> columns.stream()
.map(elem::get)
.filter(Objects::nonNull)
.collect(Collectors.joining())));
这个版本过滤掉从流,如果一些地图元素不包含在columns
列表中指定的关键可能出现null
元素。
不确定使用流,但如果你喜欢普通的java方式,它会更容易。 如果我正确地理解你的问题,这里是你想要建立的方法。您可能需要稍微调整以使其更快。
public Map<String, List<Map<String, String>>> doGrouping(List<String> columns, List<Map<String, String>> data) {
Map<String, List<Map<String, String>>> output = new HashMap<>();
for (Map<String, String> map : data) {
String key = "";
for(String column : columns) key += "".equals(key) ? (map.get(column)) : (":" + map.get(column));
output.computeIfAbsent(key, k -> Arrays.asList(map));
}
return output;
}
测试:
doGrouping(Arrays.asList("ip", "group"), fakeData)
>> {10.0.1.1:user=[{uid=tiger, ip=10.0.1.1, group=user}, {uid=woods, ip=10.0.1.1, group=user}], 10.0.1.0:admin=[{uid=root, ip=10.0.1.0, group=admin}]}
doGrouping(Arrays.asList("group"), fakeData)
>> {admin=[{uid=root, ip=10.0.1.0, group=admin}], user=[{uid=tiger, ip=10.0.1.1, group=user}, {uid=woods, ip=10.0.1.1, group=user}]}
Upvoted,因为这是一个正确的答案。只是一个建议...你可以把你的'if/else'块改成'output.computeIfAbsent(key,k - > new ArrayList ()).add(map)'。 –
这似乎是很好的建议。现在通勤,稍后再尝试并重新发布 –
我不确定我是否完全理解您尝试实施的方法的输入/输出。看起来输出类型不包含任何“n”个嵌套分组。您能否请您说明您打算如何使用您的示例数据调用'doGrouping',以及期望的输出是什么? – 4castle
你是说如果'doGrouping'的'columns'参数包含'N'个元素,那么你需要通过每个'N'元素创建嵌套的组?而且你希望每个组的键都被连接而不是嵌套? –
我在输出或接口中看不到任何会提示n级嵌套的东西。它看起来像你只是在顶层分组的多个键。 – shmosel