我试图将列表分成列表列表。在groovy中,我可以很容易地做到这一点:
def letters = 'a'..'g'
assert letters.collate(3) == [['a', 'b', 'c'], ['d', 'e', 'f'], ['g']]
Java 8中是否存在等效内容?我看过收藏家,但看起来有点复杂。我真的只想将列表中的项目分组为x。
答案 0 :(得分:2)
您可以通过Guava查看Partition API列表:
// Work out a date for which people must be born after
$max_date = \Carbon\Carbon::parse($activity->date_from)->subYears($activity->age_min);
// Filter the collection
$output = $cadets->filter(function ($cadet) {
return $cadet->birthday > $max_date;
});
返回列表的连续子列表,每个列表大小相同(最终列表可能更小)。
答案 1 :(得分:2)
这个怎么样?
char start = 'a';
char last = 'g';
int n = 3;
List<Character> letters = IntStream.rangeClosed(start, last)
.mapToObj(it -> (char) it)
.collect(toList());
List<List<Character>> result = IntStream.range(0, (letters.size() + n - 1) / n)
.map(i -> i * n)
.mapToObj(i -> letters.subList(i, Math.min(i + n, letters.size())))
.collect(toList());
或
List<List<Character>> result = IntStream.range(0, letters.size()).boxed().
collect(collectingAndThen(
groupingBy(i -> i / n, mapping(letters::get, toList())),
map -> new ArrayList<>(map.values())
));
答案 2 :(得分:1)
之前已经讨论过了,但我现在找不到它,所以这里有一个简洁的方法:
private static <T> Collector<T, ?, List<List<T>>> partitioning(int size) {
class Acc {
int count = 0;
List<List<T>> list = new ArrayList<>();
void add(T elem) {
int index = count++ / size;
if (index == list.size()) {
list.add(new ArrayList<>());
}
list.get(index).add(elem);
}
Acc merge(Acc right) {
List<T> lastLeftList = list.get(list.size() - 1);
List<T> firstRightList = right.list.get(0);
int lastLeftSize = lastLeftList.size();
int firstRightSize = firstRightList.size();
// they are both size, simply addAll will work
if (lastLeftSize + firstRightSize == 2 * size) {
System.out.println("Perfect!");
list.addAll(right.list);
return this;
}
// last and first from each chunk are merged "perfectly"
if (lastLeftSize + firstRightSize == size) {
System.out.println("Almost perfect");
int x = 0;
while (x < firstRightSize) {
lastLeftList.add(firstRightList.remove(x));
--firstRightSize;
}
right.list.remove(0);
list.addAll(right.list);
return this;
}
right.list.stream().flatMap(List::stream).forEach(this::add);
return this;
}
public List<List<T>> finisher() {
return list;
}
}
return Collector.of(Acc::new, Acc::add, Acc::merge, Acc::finisher);
}
用法:
List<List<Integer>> list = Arrays.asList(1, 3, 4, 5, 9, 8, 7)
.stream()
.parallel()
.collect(partitioning(3));
问题在于通过combiner
对并行流做得很好。更少的代码并不意味着更好或更有效的解决方案。
答案 3 :(得分:0)
试试我的图书馆AbacusUtil
x