你对减少的理解是错误的. reduce将重复对所有元素应用函数以获得单个结果.
你似乎认为减少就像做
1, 2, 3, 5, 6, 8, 9, 10
│ │ │ │ │ │ │ │
└op┘ └op┘ └op┘ └op┘
│ │ │ │
result list
事实上,确实如此
1, 2, 3, 5, 6, 8, 9, 10
│ │ │ │ │ │ │ │
└op┘ └op┘ └op┘ └op┘
│ │ │ │
└─op─┘ └─op─┘
│ │
└────op────┘
│
final result value
虽然这是一个概念视图,但确切的操作顺序是未指定的.顺序执行将类似于(((1 op 2)op 3)op 4)…而并行执行将是执行的混合,如上面的树和部分顺序执行.
如果首先将每个元素转换为List,然后使用连接每个列表的列表操作,则可以滥用reduce来创建结果列表,但是,这有两个问题:
>它没有提供所需的“跳过每个第二个元素(原始列表)”逻辑;如果你看一下上面的树,它应该变得清楚,不可能在每个可能的执行场景中形成一个正确的op函数.
>创建临时列表并连接它们是非常低效的
后一点可以通过使用collect来解决,这是一个可变的减少,因此,允许你使用可以添加项目的可变列表,但是,它没有解决第一点,包括所需的过滤器会违反合同和仅适用于顺序执行.
所以解决方案是为源列表范围内的所有元素定义一个过滤器,然后使用collect创建结果列表的可变缩减,并且,大惊喜,这正是您原始代码的作用:
… .filter(integer -> integer % 2 == 0).collect(Collectors.toList());