我想使用Iterable<String>
和谓词来选择要保留的字符串,以进行字符串列表过滤,其他字符串必须从列表中删除,但是我并没有低估我如何进行删除。
static <T> Iterable<T> select(Iterable<T> it, Predicate<T> pred) {
for (T s: it) {
if (pred.test(s)==false) {
// what to do here?
}
}
return ...;
}
对于此输入:
{"a","","b",""}
我希望
{"a","b"}
答案 0 :(得分:3)
import com.sourcesense.sisal.socialbetting.dev.example.elastic.service.QuarkusElasticService;
import io.quarkus.vertx.ConsumeEvent;
import io.reactiverse.elasticsearch.client.RestHighLevelClient;
import io.vertx.core.Vertx;
import io.vertx.core.json.JsonObject;
import org.apache.http.HttpHost;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
public class QuarkusElasticServiceImpl implements QuarkusElasticService {
@Inject
Vertx vertx;
private RestHighLevelClient esClient;
@PostConstruct
public void init() {
RestClientBuilder builder = RestClient.builder(
new HttpHost("localhost", 9200, "http"),
new HttpHost("localhost", 9201, "http"));
esClient = RestHighLevelClient.create(vertx, builder);
}
@Override
@ConsumeEvent("QuarkusElasticService.getReq")
public CompletionStage<JsonObject> getReq(JsonObject jsonObject) {
CompletableFuture future = new CompletableFuture();
GetRequest getRequest = new GetRequest(
jsonObject.getString("index"),
jsonObject.getString("id"));
esClient.getAsync(getRequest, RequestOptions.DEFAULT, ar -> {
if (ar.failed()) {
future.completeExceptionally(new Exception("erroraccio"));
} else {
future.complete(JsonObject.mapFrom(ar.result()));
}
});
return future;
}
}
代表根据请求提供Iterable
的能力。因此,要使用过滤逻辑装饰现有的可迭代对象,必须实现装饰Iterator
。
Iterator
您可以通过
进行测试static <T> Iterable<T> select(Iterable<T> it, Predicate<T> pred) {
return () -> new Iterator<T>() {
Iterator<T> sourceIterator = it.iterator();
T current;
boolean hasCurrent;
@Override
public boolean hasNext() {
while(!hasCurrent) {
if(!sourceIterator.hasNext()) {
return false;
}
T next = sourceIterator.next();
if(pred.test(next)) {
current = next;
hasCurrent = true;
}
}
return true;
}
@Override
public T next() {
if(!hasNext()) throw new NoSuchElementException();
T next = current;
current = null;
hasCurrent = false;
return next;
}
};
}
实现这样的List<String> original = new ArrayList<>();
Collections.addAll(original, "foo", "bar", "baz");
Iterable<String> filter = select(original, s -> s.startsWith("b"));
System.out.println(String.join(", ", filter));
original.removeIf(s -> !s.endsWith("r"));
System.out.println(String.join(", ", filter));
时,最大的挑战是为Iterator
和hasNext
这两个方法提供正确的语义,而又不保证调用者如何调用它们,即您不能假定它将永远不会调用next
两次,也不能假定总是用前面的hasNext()
来调用next()
。
使用Stream API可以更轻松地实现相同的逻辑:
hasNext()
答案 1 :(得分:1)
由于任何Collection
是Iterable
,只需将符合条件的项目添加到新集合中,然后再返回即可:
static <T> Iterable<T> select(Iterable<T> it, Predicate<T> pred) {
Collection<T> collection = new ArrayList<>();
for (T s: it) {
if (!pred.test(s)) {
collection.add(s);
}
}
return collection;
}
很少有见解:
pred.test(s)==false
表达式应简化为!pred.test(s)
可以使用java-stream来缩短方法的全部内容:
static <T> Iterable<T> select(Iterable<T> it, Predicate<T> pred) {
return StreamSupport.stream(it.spliterator(), false)
.filter(pred)
.collect(Collectors.toList());
}
答案 2 :(得分:0)
首先将您的Iterable<T>
包裹到Stream<T>
中:
普通Java:
StreamSupport.stream(it.spliterator(), false)
Streams.stream(it)
StreamEx.of(it.iterator())
然后通过您的Predicate<T>
对其进行过滤:
...
stream.filter(pred.negate())
...
最后返回Iterable<T>
:
为lambda
:
return () -> stream.iterator();
为method reference
return stream::iterator;
完整示例:
static <T> Iterable<T> select(Iterable<T> it, Predicate<T> pred) {
return StreamSupport.stream(it.spliterator(), false).filter(pred.negate())::iterator;
}
或:
static <T> Iterable<T> select(Iterable<T> it, Predicate<T> pred) {
Stream<T> stream = stream(it.spliterator(), false);
Predicate<T> negatedPred = pred.negate();
Stream<T> filteredStream = stream.filter(negatedPred);
return filteredStream::iterator;
}
答案 3 :(得分:0)
我在评论中表示的Holger替代解决方案如下:
static <T> Iterable<T> select(Iterable<T> toIterate, Predicate<T> pred) {
return () -> new Iterator<T>() {
Iterator<T> delegate = toIterate.iterator();
T next = findNextValid();
public boolean hasNext() {
return next != null;
}
public T next() {
if (next == null) throw new NoSuchElementException();
T result = next;
next = findNextValid();
return result;
}
private T findNextValid() {
T result = null;
while (result == null && delegate.hasNext()) {
T candidate = delegate.next();
if (pred.test(candidate)) {
result = candidate;
}
}
return result;
}
};
}
不同之处在于,hasCurrent
不需要额外的标记,并且它在实际请求下一个元素之前使Iterator
前进。您可能会认为后者是不可取的。