使用Java8流API处理HashMap

使用Java8流API处理HashMap,java,hashmap,java-stream,Java,Hashmap,Java Stream,我在表单中有一个哈希表 Map<String, Map<String,Double> 特别是,输出必须具有相同的键(id1,…,IDN) 内部哈希表必须具有固定键(1/1/1800)和已处理值 我的当前(不工作)代码: output=input.entrySet() .stream() .收集( Collectors.toMap(entry->entry.getKey(), 条目->收集器.toMap( e->“1/1/2000”, e->{ //获取输入数组 List Li

我在表单中有一个哈希表

Map<String, Map<String,Double>
特别是,输出必须具有相同的键(id1,…,IDN) 内部哈希表必须具有固定键(1/1/1800)和已处理值

我的当前(不工作)代码:

output=input.entrySet()
.stream()
.收集(
Collectors.toMap(entry->entry.getKey(),
条目->收集器.toMap(
e->“1/1/2000”,
e->{
//获取输入数组
List List=entry.getValue().values().stream()
.collect(Collectors.toList());
DescriptiveStatistics stats=新的DescriptiveStatistics();
//从输入数组中删除NaN值
列表。forEach(v->{
如果(!new Double((Double)v).isNaN())
统计附加值((双)v);
});
double value=stats.max();
返回值;
}));
问题在哪里


谢谢

问题是试图调用
收集器。toMap
在第一个
收集器内的第二种类型。toMap
收集器。toMap
应传递给接受
收集器的方法

有一种方法可以实现您的目标:

Map<String, Map<String,Double>>
output = input.entrySet()
              .stream()
              .collect(Collectors.toMap(e -> e.getKey(),
                                        e -> Collections.singletonMap (
                                            "1/1/1800",
                                            e.getValue()
                                             .values()
                                             .stream()
                                             .filter (d->!Double.isNaN (d))
                                             .mapToDouble (Double::doubleValue)
                                             .max()
                                             .orElse(0.0))));
Map
output=input.entrySet()
.stream()
.collect(Collectors.toMap(e->e.getKey(),
e->Collections.singletonMap(
"1/1/1800",
e、 getValue()
.values()
.stream()
.filter(d->!Double.isNaN(d))
.mapToDouble(双精度::双精度值)
.max()
.orElse(0.0));

请注意,不需要第二个
Collectors.toMap
。输出的内部
Map
s每个都有一个条目,因此您可以使用
Collections.singletonMap
创建它们。

问题是试图调用
收集器.toMap
第一个
收集器内的第二个类型。toMap
Collectors.toMap
应传递给接受
收集器的方法

有一种方法可以实现您的目标:

Map<String, Map<String,Double>>
output = input.entrySet()
              .stream()
              .collect(Collectors.toMap(e -> e.getKey(),
                                        e -> Collections.singletonMap (
                                            "1/1/1800",
                                            e.getValue()
                                             .values()
                                             .stream()
                                             .filter (d->!Double.isNaN (d))
                                             .mapToDouble (Double::doubleValue)
                                             .max()
                                             .orElse(0.0))));
Map
output=input.entrySet()
.stream()
.collect(Collectors.toMap(e->e.getKey(),
e->Collections.singletonMap(
"1/1/1800",
e、 getValue()
.values()
.stream()
.filter(d->!Double.isNaN(d))
.mapToDouble(双精度::双精度值)
.max()
.orElse(0.0));

请注意,不需要第二个
收集器。toMap
。输出的内部
映射
各有一个条目,因此您可以使用
集合。singletonMap
来创建它们。

您的原始代码可以使用
集合来解决。singletonMap
而不是
收集器。toMap

Map<String, Map<String,Double>> output = input.entrySet()
                .stream()
                .collect(
                        Collectors.toMap(entry -> entry.getKey(), 
                            entry -> {
                                // Get input array
                                List<Object> list = entry.getValue().values().stream()
                                        .collect(Collectors.toList());

                                DescriptiveStatistics stats = new DescriptiveStatistics();

                                // Remove the NaN values from the input array
                                list.forEach(v -> {
                                    if(!new Double((double)v).isNaN()) 
                                        stats.addValue((double)v);
                                });

                                double value = stats.max();                         

                                return Collections.singletonMap("1/1/2000", value);
                            }));
虽然这是一个安静的巴洛克式的解决方案

这就是说,您应该知道有一个标准使得
DescriptiveStatistics
不必要,但是,如果您只想获得最大值,这两个标准都是不必要的

此外,
List List=e.values().stream().collect(Collectors.toList());
可以简化为
List=new ArrayList(e.values());
如果确实需要
List
,但是这里,
Collection List=e.values();
就足够了,用
Double
而不是
Object
键入集合就不需要后续的类型转换

在第一个变体中使用这些改进,您将获得

Map<String, Map<String,Double>> output = input.entrySet()
            .stream()
            .collect(
                    Collectors.toMap(entry -> entry.getKey(), 
                        entry -> {
                            Collection<Double> list = entry.getValue().values();
                            DoubleSummaryStatistics stats = new DoubleSummaryStatistics();
                            list.forEach(v -> {
                                if(!Double.isNaN(v)) stats.accept(v);
                            });
                            double value = stats.getMax();                         
                            return Collections.singletonMap("1/1/2000", value);
                        }));
请注意,
double
如果至少有一个值是
NaN
,则比较结果总是计算为
false
,因此使用正确的运算符,即“value-mably-NaN”>“current max-never-NaN”,我们不需要额外的条件


现在,您可以用流操作替换循环,最终结果是。选择权在您。

您的原始代码可以使用
集合来解决。singletonMap
而不是
收集器。toMap

Map<String, Map<String,Double>> output = input.entrySet()
                .stream()
                .collect(
                        Collectors.toMap(entry -> entry.getKey(), 
                            entry -> {
                                // Get input array
                                List<Object> list = entry.getValue().values().stream()
                                        .collect(Collectors.toList());

                                DescriptiveStatistics stats = new DescriptiveStatistics();

                                // Remove the NaN values from the input array
                                list.forEach(v -> {
                                    if(!new Double((double)v).isNaN()) 
                                        stats.addValue((double)v);
                                });

                                double value = stats.max();                         

                                return Collections.singletonMap("1/1/2000", value);
                            }));
虽然这是一个安静的巴洛克式的解决方案

这就是说,您应该知道有一个标准使得
DescriptiveStatistics
不必要,但是,如果您只想获得最大值,这两个标准都是不必要的

此外,
List List=e.values().stream().collect(Collectors.toList());
可以简化为
List=new ArrayList(e.values());
如果确实需要
List
,但是这里,
Collection List=e.values();
就足够了,用
Double
而不是
Object
键入集合就不需要后续的类型转换

在第一个变体中使用这些改进,您将获得

Map<String, Map<String,Double>> output = input.entrySet()
            .stream()
            .collect(
                    Collectors.toMap(entry -> entry.getKey(), 
                        entry -> {
                            Collection<Double> list = entry.getValue().values();
                            DoubleSummaryStatistics stats = new DoubleSummaryStatistics();
                            list.forEach(v -> {
                                if(!Double.isNaN(v)) stats.accept(v);
                            });
                            double value = stats.getMax();                         
                            return Collections.singletonMap("1/1/2000", value);
                        }));
注意
Map<String, Map<String,Double>> output = input.entrySet()
            .stream()
            .collect(Collectors.toMap(entry -> entry.getKey(), 
                                      entry -> {
                                          double max = Double.NEGATIVE_INFINITY;
                                          for(double d: entry.getValue().values())
                                              if(d > max) max = d;
                                          return Collections.singletonMap("1/1/2000", max);
                                      }));