Java 8 lambda表达式:按顺序对满足给定谓词的所有项进行分组。 分组应将谓词作为关键,将项目作为值

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

// input Predicate sizeP = f -> f.length() > 1_000_000; // size filter Predicate nameP = f -> f.getName().startsWith("Plot"); // name filter List fileList; // output // files list which satisfy the filter criteria Map<Predicate,List> 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,List> rulesToFiles = new HashMap(); // [size-predicate]-> [PlotPresentation.pptx,Group.docx,PlotDiagram.docx] // [name-predicate]-> [PlotPresentation.pptx,PlotDetails.docx,PlotDiagram.docx] 

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

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

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

 Map> 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] 

这不完全是你问题中的要求,但非常有用。 也许你可以忍受这个。

但如果这不满足您,您可以对Map进行后处理:

 if(rulesToFiles.getClass()!=HashMap.class)// ensure mutable Map rulesToFiles=new HashMap<>(rulesToFiles); rulesToFiles.remove(""); // remove the none-matching items List nameAndSize = rulesToFiles.remove("name+size");// remove&check for common items if(nameAndSize!=null) {// merge them BinaryOperator> 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] 

更新:

我认为这是一个解决方案,根据请求生成Map ,首先是Stream操作,因此不需要额外的操作。 基于第一个解决方案的Map> pred ,使用:

 Map> 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]