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