如何使用流找到匹配后的项目? [英] How can one find an item after the match using streams?

查看:90
本文介绍了如何使用流找到匹配后的项目?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用Java流很容易找到与给定属性匹配的元素。

例如:

With Java streams it is easy to find an element that matches a given property.
Such as:

 String b = Stream.of("a1","b2","c3")
     .filter(s -> s.matches("b.*"))
     .findFirst().get();
 System.out.println("b = " + b);

产生:

b = b2

Produces:
b=b2

然而,通常人们在匹配后想要一个或多个值,而不是匹配本身。我只知道如何用旧时尚for循环来做这件事。

However often one wants a value or values right after a match, rather than the match itself. I only know how to do this with old fashion for loops.

    String args[] = {"-a","1","-b","2","-c","3"};
    String result = "";
    for (int i = 0; i < args.length-1; i++) {
        String arg = args[i];
        if(arg.matches("-b.*")) {
            result= args[i+1];
            break;
        }
    }
    System.out.println("result = " + result);

这将产生:

result = 2

Which will produce:
result=2

使用Java 8 Streams有一种干净的方法吗?例如,给定上面的数组和谓词 s - >设置结果为2。 s.matches( - b。*)

Is there a clean way of doing this with Java 8 Streams? For example setting result to "2" given the array above and predicate s -> s.matches("-b.*").

如果你能得到下一个值,那么它也是有用的能够获得下一个N值或所有值的列表/数组,直到匹配另一个谓词,例如 s - > s.matches( - c。*)

If you can get the next value, it would also be useful to also be able to get a list/array of the next N values or all values until another predicate is matched such as s -> s.matches("-c.*").

推荐答案

这是一种分裂者用流解决这个问题:

This is the kind of spliterator it takes to have this solved with streams:

import java.util.ArrayList;
import java.util.List;
import java.util.Spliterator;
import java.util.Spliterators.AbstractSpliterator;
import java.util.function.Consumer;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

public class PartitioningSpliterator<E> extends AbstractSpliterator<List<E>>
{
  private final Spliterator<E> spliterator;
  private final int partitionSize;

  public PartitioningSpliterator(Spliterator<E> toWrap, int partitionSize) {
    super(toWrap.estimateSize(), toWrap.characteristics());
    if (partitionSize <= 0) throw new IllegalArgumentException(
        "Partition size must be positive, but was " + partitionSize);
    this.spliterator = toWrap;
    this.partitionSize = partitionSize;
  }

  public static <E> Stream<List<E>> partition(Stream<E> in, int size) {
    return StreamSupport.stream(new PartitioningSpliterator(in.spliterator(), size), false);
  }

  @Override public boolean tryAdvance(Consumer<? super List<E>> action) {
    final HoldingConsumer<E> holder = new HoldingConsumer<>();
    if (!spliterator.tryAdvance(holder)) return false;
    final ArrayList<E> partition = new ArrayList<>(partitionSize);
    int j = 0;
    do partition.add(holder.value); while (++j < partitionSize && spliterator.tryAdvance(holder));
    action.accept(partition);
    return true;
  }

  @Override public long estimateSize() {
    final long est = spliterator.estimateSize();
    return est == Long.MAX_VALUE? est
         : est / partitionSize + (est % partitionSize > 0? 1 : 0);
  }

  static final class HoldingConsumer<T> implements Consumer<T> {
    T value;
    @Override public void accept(T value) { this.value = value; }
  }
}

一旦你把它隐藏在项目的某个地方,你可以说

Once you have this tucked away somewhere in the project, you can say

partition(Stream.of("-a","1","-b","2","-c","3"), 2)
      .filter(pair -> pair.get(0).equals("-b"))
      .findFirst()
      .map(pair -> pair.get(1))
      .orElse("");

作为一个侧面点,所提出的分裂器依赖于<$ c $的默认实现来支持并行性c> trySplit in AbstractSpliterator

As a side point, the presented spliterator supports parallelism by relying on the default implementation of trySplit in AbstractSpliterator.

这篇关于如何使用流找到匹配后的项目?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆