[英]Getting sublist from a Java list with nth elements that fulfills a condition with streams
I have a very simple use case 我有一个非常简单的用例
Given a list of letters with A and Bs, I want to get the sublist that contains the first N Bs, for example: 给定一个带有A和B的字母列表,我想获得包含前N个B的子列表,例如:
By following an imperative approach, this is relatively easy, count until we find N Bs, and then get the sublist until that position. 通过遵循命令式方法,这相对容易,计算直到找到N Bs,然后获得子列表直到该位置。
However, I couldn't find any functional solution with lambdas, since the operation on every node seems to be independent from the others (which I guess make sense for parallelization). 但是,我找不到带有lambda的任何功能解决方案,因为每个节点上的操作似乎都独立于其他节点(我认为这对于并行化是有意义的)。
If your input is a List
with fast random access, you can solve your problem using the stream of indices: 如果您的输入是具有快速随机访问的
List
,则可以使用索引流来解决问题:
public static List<String> f(int n, List<String> input) {
int fence = IntStream.range(0, input.size())
.filter(idx -> input.get(idx).equals("B")) // leave only B's
.skip(n-1)
.findFirst() // an index of n-th B
.getAsInt(); // with throw NoSuchElementException if not enough B's
return input.subList(0, fence+1);
}
Usage example: 用法示例:
System.out.println(f(3, Arrays.asList("A", "A", "A", "B", "A", "B", "A", "B", "A", "A")));
System.out.println(f(2, Arrays.asList("A", "A", "A", "B", "A", "B", "A", "B", "A", "A")));
System.out.println(f(1, Arrays.asList("A", "A", "A", "B", "A", "B", "A", "B", "A", "A")));
However despite I love Stream API I would solve this problem imperatively. 但是,尽管我喜欢Stream API,但我还是必须解决这个问题。
This code snippet do the job. 此代码段即可完成工作。
public static void main(String[] args) {
final String input = "A A A B A B A B A A";
final String[] array = input.split(" ");
final List<String> list = Arrays.asList(array);
final List<String> result = getSubList(list, 3);
System.out.println("Result=" + result);
}
public static List<String> getSubList(final List<String> list, final int limit) {
final AtomicInteger counter = new AtomicInteger();
return list.stream()
.filter(ch -> {
if (ch.equals("B") && counter.incrementAndGet() == limit) return true;
return counter.get() < limit;
})
.collect(Collectors.toList());
}
Here is code by AbacusUtil 这是AbacusUtil的代码
List<String> input = N.asList("A", "A", "A", "B", "A", "B", "A", "B", "A", "A");
List<String> list = Stream.of(input).takeWhile(MutableInt.of(3), (e, cnt) -> cnt.getAndAdd(e.equals("B") ? -1 : 0) > 0).toList();
N.println(list);
Declaration: I'm the developer of AbacusUtil. 声明:我是AbacusUtil的开发人员。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.