Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
被Java8.toMap搞糊涂了_Java_Java 8_Java Stream_Collectors - Fatal编程技术网

被Java8.toMap搞糊涂了

被Java8.toMap搞糊涂了,java,java-8,java-stream,collectors,Java,Java 8,Java Stream,Collectors,我有一个集合,如下所示,我想过滤掉所有内容,除了不是月底的日期 2010-01-01=2100.00, 2010-01-31=2108.74, 2010-02-01=2208.74, 2010-02-28=2217.92, 2010-03-01=2317.92, 2010-03-31=2327.57, 2010-04-01=2427.57, 2010-04-30=2437.67, 2010-05-01=2537.67, 2010-05-31=2548.22, 2010-06-

我有一个集合,如下所示,我想过滤掉所有内容,除了不是月底的日期

2010-01-01=2100.00, 
2010-01-31=2108.74, 
2010-02-01=2208.74, 
2010-02-28=2217.92, 
2010-03-01=2317.92, 
2010-03-31=2327.57, 
2010-04-01=2427.57, 
2010-04-30=2437.67, 
2010-05-01=2537.67, 
2010-05-31=2548.22, 
2010-06-01=2648.22, 
2010-06-30=2659.24, 
2010-07-01=2759.24, 
2010-07-31=2770.72, 
2010-08-01=2870.72, 
2010-08-31=2882.66, 
2010-09-01=2982.66, 
2010-09-30=2995.07, 
2010-10-01=3095.07, 
2010-10-31=3107.94, 
2010-11-01=3207.94, 
2010-11-30=3221.29
我有以下过滤条件
frequency.getEnd
返回与给定
LocalDate
的月末相匹配的
LocalDate

.filter(p -> frequency.getEnd(p.getKey()) == p.getKey())
所以现在我想我必须把这个过滤后的流转换回地图。我想我用一个收藏家来做这件事。因此,我补充说:

.collect(Collectors.toMap(/* HUH? */));
但我不知道如何处理
收集器.toMap
。阅读例子让我感到困惑。这是我目前的代码,显然不起作用

TreeMap<LocalDate, BigDecimal> values = values.entrySet()
                                              .stream()
                                              .filter(p -> frequency.getEnd(p.getKey()) == p.getKey())
                                              .collect(Collectors.toMap(/* HUH? */));
TreeMap values=values.entrySet()
.stream()
.filter(p->frequency.getEnd(p.getKey())==p.getKey())
.collect(Collectors.toMap(/*HUH?*/);

由于您正在迭代
Map.Entry
值,而
toMap()
只需要两种方法来提取键和值,非常简单:

Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)
请注意,这不会返回
TreeMap
。为此,您需要:

Collectors.toMap(Entry::getKey,
                 Entry::getValue,
                 (v1,v2) -> { throw new IllegalStateException("Duplicate key"); },
                 TreeMap::new)

最简单形式的toMap方法有两个参数:一个是将输入映射到键的函数,另一个是将输入映射到值的函数。两个函数的输出组合在结果映射中形成一个条目

我认为你需要这样做:

Collectors.toMap(p -> p.getKey(), p -> p.getValue())

请这样考虑您的问题:您有一个映射条目流,即
,您希望将其收集到
树映射

因此,您是对的,您应该使用
收集器.toMap
。现在,正如您在中所看到的,实际上有3个
收集器.toMap
,具体取决于参数:

  • keyMapper
    是一个函数,它的输入是流当前元素,输出是最终映射的键。因此,它将流元素映射到一个键(因此而得名)
    valueMapper
    是一个函数,其输入为流当前元素,输出为最终映射的值
  • 。前两个参数与以前相同。第三个函数,
    mergeFunction
    ,是在最终映射中的关键元素重复时调用的函数;因此,它的输入是两个值(即
    keyMapper
    返回相同键的两个值),并将这两个值合并为一个值
  • 。前三个参数与之前相同。第四个是Map的提供者:由于它目前在JDK中实现,前面的两个
    toMap
    返回一个
    HashMap
    实例。但是,如果您需要特定的映射实例,此供应商将返回该实例
在我们的特定情况下,我们需要使用第三个
toMap
,因为我们希望结果映射显式为
TreeMap
。让我们看看我们应该给它什么输入:

  • keyMapper
    :因此这应该返回最终映射的键。这里,我们处理的是一个
    ,因此每个流元素的类型都是
    Map.Entry
    。然后,此函数将
    Map.Entry e
    作为输入。它的输出应该是最终映射的键,在这种情况下,输出应该是
    e.getKey()
    ,即条目所持有的
    LocalDate
    。这可以写成lambda表达式:
    e->e.getKey()
    。这也可以写成一个方法引用
    Map.Entry::getKey
    ,但我们还是在这里使用lambdas,因为它可能更容易理解
  • valueMapper
    :这与上面相同,但在本例中,此函数需要返回
    e.getValue()
    ,即条目所持有的
    bigdecimic
    。这就是
    e->e.getValue()
  • mergeFunction
    :这是一个棘手的问题。我们知道,通过构造,最终地图中没有重复的关键元素(即没有重复的
    LocalDate
    )。我们在这里写什么?一个简单的解决方案是抛出一个异常:这不应该发生,如果发生了,在某个地方就有一个大问题。所以不管这两个输入参数是什么,我们都会抛出一个异常。这可以写成
    (v1,v2)->{throw new SomeException();}
    。请注意,它需要用括号括起来。在本例中,为了与JDK当前的功能保持一致,我选择了
    SomeException
  • mapSupplier
    :如前所述,我们想提供一个
    TreeMap
    。供应商不接受任何参数并返回一个新实例。所以这里可以写为
    ()->new TreeMap()
    。同样,我们可以使用方法引用并编写
    TreeMap::new
最后一段代码,我刚刚编写了流的收集部分(注意,在这段代码中,您也可以使用相应的方法引用,如上所述,我在注释中添加了它们):

Collectors.toMap(
e->e.getKey(),//Map.Entry::getKey
e->e.getValue(),//Map.Entry::getValue
(v1,v2)->{抛出新的IllegalStateException();},
()->new TreeMap()//TreeMap::new
)

除了前面的答案之外,请注意,如果您不需要保留原始地图,您可以在不使用流API的情况下执行此类过滤:

values.keySet().removeIf(k -> !frequency.getEnd(k).equals(k));

OP想要一个
TreeMap
作为输出,而不是当前默认的
HashMap
。我看不出他特别想要一个TreeMap。他展示了一个使用树形图的例子,树形图并不是一个要求;我意识到它不是OP的,我会的,但它也是long@njzk2嗯,我尽量说得直截了当。OP对一般的收藏家感到困惑(也许还有lambdas),所以我认为花时间来解释是件好事。我同意最后有很多关于6行代码的讨论,但是我
values.keySet().removeIf(k -> !frequency.getEnd(k).equals(k));