Java 通过谓词对集合进行分区的库方法
我有一个对象集合,我想将其划分为两个集合,其中一个传递谓词,另一个传递谓词。我希望有一个方法可以做到这一点,但最接近的是,这并没有给我其他的收集 我想象这个方法的签名是这样的:Java 通过谓词对集合进行分区的库方法,java,collections,guava,Java,Collections,Guava,我有一个对象集合,我想将其划分为两个集合,其中一个传递谓词,另一个传递谓词。我希望有一个方法可以做到这一点,但最接近的是,这并没有给我其他的收集 我想象这个方法的签名是这样的: public static <E> Pair<Collection<E>, Collection<E>> partition(Collection<E> source, Predicate<? super E> predicate) 公共静态对分区
public static <E> Pair<Collection<E>, Collection<E>> partition(Collection<E> source, Predicate<? super E> predicate)
公共静态对分区(集合源,谓词使用Guava
下面是一个示例,它将单词列表分为两部分:长度大于3的单词和长度不大于3的单词
List<String> words = Arrays.asList("foo", "bar", "hello", "world");
ImmutableListMultimap<Boolean, String> partitionedMap = Multimaps.index(words, new Function<String, Boolean>(){
@Override
public Boolean apply(String input) {
return input.length() > 3;
}
});
System.out.println(partitionedMap);
如果您使用的是(以前的GS集合),则可以在所有RichIterables
上使用partition
方法
MutableList<Integer> integers = FastList.newListWith(-3, -2, -1, 0, 1, 2, 3);
PartitionMutableList<Integer> result = integers.partition(IntegerPredicates.isEven());
Assert.assertEquals(FastList.newListWith(-2, 0, 2), result.getSelected());
Assert.assertEquals(FastList.newListWith(-3, -1, 1, 3), result.getRejected());
如果您的集合不是一个RichIterable
,您仍然可以在Eclipse集合中使用静态实用程序
PartitionIterable<Integer> partitionIterable = Iterate.partition(integers, IntegerPredicates.isEven());
PartitionMutableList<Integer> partitionList = ListIterate.partition(integers, IntegerPredicates.isEven());
partitionTable partitionTable=Iterate.partition(integers,IntegerPredicates.isEven());
PartitionMutableList partitionList=ListIterate.partition(integers,IntegerPredicates.isEven());
注意:我是Eclipse集合的提交者。使用新的java 8功能(和),您可以编写:
PartitionIterable<Integer> partitionIterable = Iterate.partition(integers, IntegerPredicates.isEven());
PartitionMutableList<Integer> partitionList = ListIterate.partition(integers, IntegerPredicates.isEven());
List<String> words = Arrays.asList("foo", "bar", "hello", "world");
Map<Boolean, List<String>> partitionedMap =
words.stream().collect(
Collectors.partitioningBy(word -> word.length() > 3));
System.out.println(partitionedMap);
List words=Arrays.asList(“foo”、“bar”、“hello”、“world”);
地图分区地图=
words.stream().collect(
Collectors.partitionby(word->word.length()>3));
System.out.println(分区地图);
提供了基于一个或多个谓词对Iterable
对象进行分区的方法。(查找分区(…)
方法。)请注意,如果预先知道的分区键集有限,则只需针对每个分区键再次迭代集合,跳过每次迭代中的所有不同键项,可能会更有效。因为这样不会为垃圾收集器分配许多新对象
LocalDate start = LocalDate.now().with(TemporalAdjusters.firstDayOfYear());
LocalDate endExclusive = LocalDate.now().plusYears(1);
List<LocalDate> daysCollection = Stream.iterate(start, date -> date.plusDays(1))
.limit(ChronoUnit.DAYS.between(start, endExclusive))
.collect(Collectors.toList());
List<DayOfWeek> keys = Arrays.asList(DayOfWeek.values());
for (DayOfWeek key : keys) {
int count = 0;
for (LocalDate day : daysCollection) {
if (key == day.getDayOfWeek()) {
++count;
}
}
System.out.println(String.format("%s: %d days in this year", key, count));
}
对于新的Java 12收集器::teeing
:
var dividedStrings = Stream.of("foo", "hello", "bar", "world")
.collect(Collectors.teeing(
Collectors.filtering(s -> s.length() <= 3, Collectors.toList()),
Collectors.filtering(s -> s.length() > 3, Collectors.toList()),
List::of
));
System.out.println(dividedStrings.get(0)); //[foo, bar]
System.out.println(dividedStrings.get(1)); //[hello, world]
var dividedStrings=Stream.of(“foo”、“hello”、“bar”、“world”)
收集(
Collectors.filtering(s->s.length()s.length()>3,Collectors.toList()),
列表::的
));
System.out.println(dividedStrings.get(0));//[foo,bar]
System.out.println(dividedStrings.get(1));//[hello,world]
你可以找到更多的例子。谢谢,我没有想到要看那里。如果你已经有了一个谓词,你可以将它转换成一个带有Functions.forPredicate.Update for Java 8的函数:流包Java.util.stream.Collectors#groupingBy(Java.util.Function.Function)中也提供了类似的方法
类似于words.stream().collect(collector.groupingBy(func))
@PeterandtheWolf根据您的建议,我添加了一个答案。注意,如果预先知道的分区密钥集有限,只需对每个分区密钥重复一次集合,跳过每次迭代中所有不同的密钥项,GC效率可能会更高。另一种GC友好和封装的方法是我们INGJava8围绕原始集合过滤包装流:有人知道分区函数第一次出现在集合库中的时间/地点吗?
List<AbstractMap.SimpleEntry<DayOfWeek, Stream<LocalDate>>> partitions = keys.stream().map(
key -> new AbstractMap.SimpleEntry<>(
key, daysCollection.stream().filter(
day -> key == day.getDayOfWeek())))
.collect(Collectors.toList());
// partitions could be passed somewhere before being used
partitions.forEach(pair -> System.out.println(
String.format("%s: %d days in this year", pair.getKey(), pair.getValue().count())));
MONDAY: 57 days in this year
TUESDAY: 57 days in this year
WEDNESDAY: 57 days in this year
THURSDAY: 57 days in this year
FRIDAY: 56 days in this year
SATURDAY: 56 days in this year
SUNDAY: 56 days in this year
var dividedStrings = Stream.of("foo", "hello", "bar", "world")
.collect(Collectors.teeing(
Collectors.filtering(s -> s.length() <= 3, Collectors.toList()),
Collectors.filtering(s -> s.length() > 3, Collectors.toList()),
List::of
));
System.out.println(dividedStrings.get(0)); //[foo, bar]
System.out.println(dividedStrings.get(1)); //[hello, world]