Java 8 lambda表达式:按顺序对满足给定谓词的所有项进行分组。分组应将谓词作为关键,将项目作为值 [英] Java 8 lambda expression: Group all items in sequence which satisfy the given predicate. Grouping shall have predicate as key, items as value

查看:162
本文介绍了Java 8 lambda表达式:按顺序对满足给定谓词的所有项进行分组。分组应将谓词作为关键,将项目作为值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是示例输入数据和预期输出。我想在输入列表上单次迭代执行此操作

Here is the sample input data and expected output. I want perform this operation with single iteration on the input list.

// input
Predicate<File> sizeP = f -> f.length() > 1_000_000; // size filter
Predicate<File> nameP = f -> f.getName().startsWith("Plot"); // name filter
List<File> fileList;
// output
// files list which satisfy the filter criteria
Map<Predicate<File>,List<File>> rulesToFiles = new HashMap<>();

// Example data
//  1. PlotPresentation.pptx-> 2 MB size      
//  2. Gen.docx-> 500 KB size
//  3. Group.docx-> 1.5 MB size
//  4. PlotDetails.docx-> 850 KB size
//  5. PlotDiagram.docx-> 5 MB size

// my map should have
Map<Predicate<File>,List<File>> rulesToFiles = new HashMap<>();
// [size-predicate]-> [PlotPresentation.pptx,Group.docx,PlotDiagram.docx]
// [name-predicate]-> [PlotPresentation.pptx,PlotDetails.docx,PlotDiagram.docx]


推荐答案

为了将有用的键与谓词相关联,我们可以使用 Map

In order to associate useful keys with predicates, we may use a Map:

Map<String, Predicate<File>> pred=new TreeMap<>();
pred.put("size", f -> f.length() > 1_000_000);
pred.put("name", f -> f.getName().startsWith("Plot"));

然后我们可以像这样处理它们:

Then we can process them like this:

Map<String,List<File>> rulesToFiles = 
    fileList.stream().collect(Collectors.groupingBy(f->
        pred.entrySet().stream().filter(e->e.getValue().test(f))
            .map(Map.Entry::getKey).collect(Collectors.joining("+"))
    ));

这导致

 => [Gen.docx]
size => [Group.docx]
name => [PlotDetails.docx]
name+size => [PlotPresentation.pptx, PlotDiagram.docx]

这与你问题中的要求不完全相同有用。也许你可以忍受。

which isn’t exactly as requested in your question but quite useful. Maybe you can live with that.

但如果这不满足你,你可以对地图

But if this doesn’t satisfy you, you may apply a post-processing to the Map:

if(rulesToFiles.getClass()!=HashMap.class)// ensure mutable Map
    rulesToFiles=new HashMap<>(rulesToFiles);

rulesToFiles.remove(""); // remove the none-matching items
List<File> nameAndSize = rulesToFiles.remove("name+size");// remove&check for common items
if(nameAndSize!=null) {// merge them
    BinaryOperator<List<File>> merger=(a,b)->
        Stream.concat(a.stream(), b.stream()).collect(Collectors.toList());
    rulesToFiles.merge("size", nameAndSize, merger);
    rulesToFiles.merge("name", nameAndSize, merger);
}

结果:

size => [Group.docx, PlotPresentation.pptx, PlotDiagram.docx]
name => [PlotDetails.docx, PlotPresentation.pptx, PlotDiagram.docx]






更新:



我认为这是一个解决方案,按要求生成地图首先是 Stream 操作,因此不需要额外的操作。基于 Map< String,Predicate< File>>第一个解决方案的pred ,使用:


Update:

I thought it over and here’s a solution to produce a Map as requested, right by the Stream operation in the first place, so no additional operation is required. Based on the Map<String, Predicate<File>> pred of the first solution, use:

Map<String,List<File>> rulesToFiles = fileList.stream()
    .flatMap(f -> pred.entrySet().stream().filter(e->e.getValue().test(f))
        .map(e->new AbstractMap.SimpleEntry<>(e.getKey(), f)))
    .collect(Collectors.groupingBy(Map.Entry::getKey,
        Collectors.mapping(Map.Entry::getValue, Collectors.toList())));

结果:

size => [PlotPresentation.pptx, Group.docx, PlotDiagram.docx]
name => [PlotPresentation.pptx, PlotDetails.docx, PlotDiagram.docx]

这篇关于Java 8 lambda表达式:按顺序对满足给定谓词的所有项进行分组。分组应将谓词作为关键,将项目作为值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆