使用Java流,很容易找到与给定属性匹配的元素 如:
String b = Stream.of("a1","b2","c3")
.filter(s -> s.matches("b.*"))
.findFirst().get();
System.out.println("b = " + b);
产地:
B = B2
然而,通常人们在匹配后想要一个或多个值,而不是匹配本身。我只知道如何用旧时尚圈来做到这一点。
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);
将产生:
结果= 2
使用Java 8 Streams有一种干净的方法吗?例如,将结果设置为&#34; 2&#34;给定上面的数组和谓词s -> s.matches("-b.*")
。
如果你可以获得下一个值,那么能够获得下一个N值或所有值的列表/数组,直到匹配另一个谓词,例如s -> s.matches("-c.*")
,这也是有用的。
答案 0 :(得分:3)
我通过这篇博文发现了它:
http://blog.jooq.org/2014/09/10/when-the-java-8-streams-api-is-not-enough/
名为jOOL的库有一个Github链接
https://github.com/jOOQ/jOOL
和Maven中心信息在这里:
http://mvnrepository.com/artifact/org.jooq/jool/0.9.6
该示例的代码变为:
import org.jooq.lambda.Seq;
...
String result = Seq.of(args)
.skipWhile(s -> !s.matches("-b.*"))
.skip(1)
.findFirst()
.get();
答案 1 :(得分:3)
这是用流解决这个问题的分裂器:
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; }
}
}
一旦你把它隐藏在项目的某个地方,你可以说
partition(Stream.of("-a","1","-b","2","-c","3"), 2)
.filter(pair -> pair.get(0).equals("-b"))
.findFirst()
.map(pair -> pair.get(1))
.orElse("");
作为一个侧面点,所提出的分词符依赖于trySplit
中AbstractSpliterator
的默认实现来支持并行性。
答案 2 :(得分:1)
我不能说以下是有效的,但它遵循一个容易应用的模式。 (但在实际的函数式语言中,添加过滤器时效率可能会很高。)
首先从字符串流中收集[[-c, 3], [-b, 2], [-a, 1]]
。
List<List<String>> optionLists = Stream.of("-a","1","-b","2","-c","3")
.collect(ArrayList<List<String>>::new,
(lists, arg) -> {
if (arg.startsWith("-")) {
List<String> list = new LinkedList<>();
list.add(arg);
lists.add(0, list);
} else {
List<String> list = lists.get(0);
list.add(arg);
}
},
List::addAll);
System.out.println(optionLists);
然后可以在地图中将其转换为所有选项。
List<String> bargs = optionLists.stream()
.collect(Collectors.toMap(lst -> lst.get(0),
lst -> lst.subList(1, lst.size()))).get("-b");
System.out.println("For -b: " + bargs);
答案 3 :(得分:1)
据我所知,这似乎并不是一种简单的方法,其中很多原因都源于Java的Stream API缺乏的缺点。获取流元素的索引以及将流压缩在一起的能力。
如果我们可以获取流中某个元素的索引,然后只需使用与.limit(n)函数配对的.skip()函数来丢弃这些元素,我们可以想象一个简单的问题解决方案。包括所需的匹配点,然后将结果限制为下一个n个元素。
您可能需要查看Protonpack,这是一个用于Java 8的&#34; Streams实用程序库,提供takeWhile,skipWhile,zip和展开。&#34;使用此库可以轻松解决问题:
Stream<String> stringStream = Stream.of("-a","1","-b","2","-c","3");
Stream<String> nAfterMatch =
StreamUtils.skipWhile(stringStream, s -> !(s.matches("-b.*")))
.limit(n);
答案 4 :(得分:0)
对于您希望直接使用som Pair
或Tuple
类之后的值的情况。
String b = Stream.of(Pair.of("-a","1"),Pair.of("-b","2"),Pair.of("-c","3"))
.filter(p -> p.first.matches("-b.*"))
.map(p -> p.second)
.findFirst().get();
答案 5 :(得分:0)
这可以是解决方案解决方案:
String[] args = {"-a","1","-b","2","-c","3"};
String b = IntStream.range(1, args.length)
.mapToObj(i -> new Pair<>(args[i-1], args[i]))
.filter(pp -> pp.getFirst().startsWith("-b"))
.findFirst().get().getSecond();
System.out.println("b = " + b);
//=> Output: b = 2
.mapToObj
用于使用来自输入数组args
的连续索引从args
数组生成字符串值对。
答案 6 :(得分:0)
由于Java流takeWhile
,有可能:
Stream<String> strings = Stream.of("a1","b2","c3");
final AtomicBoolean matchFound = new AtomicBoolean(false);
final AtomicReference<String> stringAfterMatch = new AtomicReference<>();
strings.takeWhile(string -> stringAfterMatch.get() == null).forEach(string -> {
if (matchFound.get()) {
stringAfterMatch.set(string);
}
if (string.matches("b.*")) {
matchFound.set(true);
}
});
String b = stringAfterMatch.get();
答案 7 :(得分:0)
private static boolean containsWords(String input, String[] words) {
Arrays.stream(words).allMatch(new Predicate<String>() {
@Override
public boolean test(String t) {
if(input.contains(t))
counter+=1; //add a global counter
//ExtensionUtils.keyWordHash.put(t, input); // or you can put the strings to a hashmap and retrieve later
return input.contains(t);
}
});
return Arrays.stream(words).allMatch(input::contains);
}