Java 在列表和jdk8上使用流、过滤器和平均值
我有这样的数据列表:Java 在列表和jdk8上使用流、过滤器和平均值,java,list,filter,java-8,java-stream,Java,List,Filter,Java 8,Java Stream,我有这样的数据列表: {id, datastring} {1,"a:1|b:2|d:3"} {2,"a:2|c:2|c:4"} {3,"a:2|bb:2|a:3"} {4,"a:3|e:2|ff:3"} 这里我需要做的是做一些操作,比如平均或查找字符串中某个元素小于某个值的所有id 这里有一些例子 平均数 {a,2}{b,2}{bb,2}{c,3}{d,3}{e,2}{ff,3} 查找所有id,其中c是的,您可以使用流操作来实现这一点,但我建议为这些数据创建一个类,以便每行对应一个特定实例
{id, datastring}
{1,"a:1|b:2|d:3"}
{2,"a:2|c:2|c:4"}
{3,"a:2|bb:2|a:3"}
{4,"a:3|e:2|ff:3"}
这里我需要做的是做一些操作,比如平均或查找字符串中某个元素小于某个值的所有id
这里有一些例子
平均数
{a,2}{b,2}{bb,2}{c,3}{d,3}{e,2}{ff,3}
查找所有id,其中c是的,您可以使用流操作来实现这一点,但我建议为这些数据创建一个类,以便每行对应一个特定实例。那会让你的生活更轻松
class Data {
private int id;
private Map<String, List<Integer>> map;
....
}
一般的请求有点棘手。我以另一个实现结束,您最终得到了一个Map
(它确实包含平均值)以及其他信息
Map<String, IntSummaryStatistics> stats = list.stream()
.flatMap(d -> d.getMap().entrySet().stream())
.collect(toMap(Map.Entry::getKey,
e -> e.getValue().stream().mapToInt(i -> i).summaryStatistics(),
(i1, i2) -> {i1.combine(i2); return i1;}));
你可以很容易地从中得出平均值
这是一个完整的示例,但实施肯定会有所改进。我知道您有您的答案,但以下是我的版本:
Map<String, Double> result = list.stream()
.map(Data::getElements)
.flatMap((Multimap<String, Integer> map) -> {
return map.entries().stream();
})
.collect(Collectors.groupingBy(Map.Entry::getKey,
Collectors.averagingInt((Entry<String, Integer> token) -> {
return token.getValue();
})));
System.out.println(result);
List<Integer> result2 = list.stream()
.filter((Data data) -> {
return data.getElements().get("c").stream().anyMatch(i -> i < 4);
})
.map(Data::getId)
.collect(Collectors.toList());
System.out.println(result2);
Map result=list.stream()
.map(数据::getElements)
.flatMap((多贴图)->{
返回map.entries().stream();
})
.collect(Collectors.groupingBy(Map.Entry::getKey、,
收集器.averagint((入口令牌)->{
返回token.getValue();
})));
系统输出打印项次(结果);
List result2=List.stream()
.filter((数据)->{
返回data.getElements().get(“c”).stream().anyMatch(i->i<4);
})
.map(数据::getId)
.collect(Collectors.toList());
系统输出打印项次(结果2);
是。是的。(如果我没弄错的话)谢谢亚历克西斯,我只是试了一下,它似乎真的达到了我的预期。明天我将更深入地研究它,因为它有很多我还不熟悉的新内容。注意,您可以使用getOrDefault
代替两个filter
:stream().filter(d->d.getMap().getOrDefault(id,emptyList()).stream().anyMatch(谓词)).map(…)
Hi Alexis,如何用sqlResults的输出替换Files.lines()加载?类型为java.sql.ResultSet的sqlResult我不熟悉.map和.collect(toList())谢谢这里/如何定义“emptyList()”?@AndreCouture嗨,对于ResultSet部分,您可以检查以下内容:。基本上是一个while循环,然后在列表中添加一个新的数据对象emptyList()
只是Collections
类中返回空列表的静态方法。另外,由于这些数据是从数据库中获取的,所以直接使用SQL查询可能更简单?它也将更加有效。或者只是为了练习新的Java8特性?
public static Set<Integer> ids(List<Data> list, String value, Predicate<Integer> boundPredicate) {
return list.stream()
.filter(d -> d.getMap().containsKey(value))
.filter(d -> d.getMap().get(value).stream().anyMatch(boundPredicate))
.map(d -> d.getId())
.collect(toSet());
}
Set<Integer> set = ids(list, "a", value -> value < 3);
[1, 2, 3]
Map<String, IntSummaryStatistics> stats = list.stream()
.flatMap(d -> d.getMap().entrySet().stream())
.collect(toMap(Map.Entry::getKey,
e -> e.getValue().stream().mapToInt(i -> i).summaryStatistics(),
(i1, i2) -> {i1.combine(i2); return i1;}));
ff => IntSummaryStatistics{count=1, sum=3, min=3, average=3.000000, max=3}
bb => IntSummaryStatistics{count=1, sum=2, min=2, average=2.000000, max=2}
a => IntSummaryStatistics{count=5, sum=11, min=1, average=2.200000, max=3}
b => IntSummaryStatistics{count=1, sum=2, min=2, average=2.000000, max=2}
c => IntSummaryStatistics{count=2, sum=6, min=2, average=3.000000, max=4}
d => IntSummaryStatistics{count=1, sum=3, min=3, average=3.000000, max=3}
e => IntSummaryStatistics{count=1, sum=2, min=2, average=2.000000, max=2}
Map<String, Double> result = list.stream()
.map(Data::getElements)
.flatMap((Multimap<String, Integer> map) -> {
return map.entries().stream();
})
.collect(Collectors.groupingBy(Map.Entry::getKey,
Collectors.averagingInt((Entry<String, Integer> token) -> {
return token.getValue();
})));
System.out.println(result);
List<Integer> result2 = list.stream()
.filter((Data data) -> {
return data.getElements().get("c").stream().anyMatch(i -> i < 4);
})
.map(Data::getId)
.collect(Collectors.toList());
System.out.println(result2);