java 如何使用java8通过谓词对列表进行分区?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36678571/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 01:44:42  来源:igfitidea点击:

How to partition a list by predicate using java8?

javalistjava-8java-stream

提问by Elad Benda

I have a list awhich i want to split to few small lists.

我有一个列表a,我想将其拆分为几个小列表。

say all the items that contains with "aaa", all that contains with "bbb" and some more predicates.

说所有包含“aaa”的项目,所有包含“bbb”的项目和一些更多的谓词。

How can I do so using java8?

我怎样才能使用 java8 做到这一点?

I saw this postbut it only splits to 2 lists.

我看到了这篇文章,但它只分为 2 个列表。

public void partition_list_java8() {

    Predicate<String> startWithS = p -> p.toLowerCase().startsWith("s");

    Map<Boolean, List<String>> decisionsByS = playerDecisions.stream()
            .collect(Collectors.partitioningBy(startWithS));

    logger.info(decisionsByS);

    assertTrue(decisionsByS.get(Boolean.TRUE).size() == 3);
}

I saw this post, but it was very old, before java 8.

我看到了这篇文章,但它已经很老了,在 java 8 之前。

回答by Pshemo

Like it was explained in @RealSkepticcommentPredicatecan return only two results: true and false. This means you would be able to split your data only in two groups.
What you need is some kind of Functionwhich will allow you to determine some common result for elements which should be grouped together. In your case such result could be first character in its lowercase (assuming that all strings are not empty - have at least one character).

就像@RealSkeptic中解释的那样,注释Predicate只能返回两个结果:true 和 false。这意味着您只能将数据分成两组。
您需要的是某种Function可以让您确定应该组合在一起的元素的一些常见结果。在您的情况下,这样的结果可能是小写的第一个字符(假设所有字符串都不为空 - 至少有一个字符)。

Now with Collectors.groupingBy(function)you can group all elements in separate Lists and store them in Map where key will be common result used for grouping (like first character).

现在,Collectors.groupingBy(function)您可以将所有元素分组在单独的列表中,并将它们存储在 Map 中,其中键将是用于分组的常用结果(如第一个字符)。

So your code can look like

所以你的代码看起来像

Function<String, Character> firstChar =  s -> Character.toLowerCase(s.charAt(0));

List<String> a = Arrays.asList("foo", "Abc", "bar", "baz", "aBc");
Map<Character, List<String>> collect = a.stream()
        .collect(Collectors.groupingBy(firstChar));

System.out.println(collect);

Output:

输出:

{a=[Abc, aBc], b=[bar, baz], f=[foo]}

回答by yshavit

You can use Collectors.groupingByto turn your stream of (grouping) -> (list of things in that grouping). If you don't care about the groupings themselves, then call values()on that map to get a Collection<List<String>>of your partitions.

你可以用Collectors.groupingBy你的流(分组)->(该分组中的事物列表)。如果您不关心分组本身,则调用values()该映射以获取Collection<List<String>>您的分区。