Java Streams迭代ResultSet对象 [英] Java Streams to iterate over a ResultSet object
问题描述
我有以下代码片段
ResultSet rs = stmt.executeQuery();
List<String> userIdList = new ArrayList<String>();
while(rs.next()){
userIdList.add(rs.getString(1));
}
我是否可以使用Java流/ Lambda表达式来执行此迭代而不是一个while循环来填充List?
Can I make use of Java streams/Lambda expressions to perform this iteration instead of a while loop to populate the List?
推荐答案
您可以为 ResultSet $创建一个包装器c $ c>将其设为
Iterable
。从那里你可以迭代,也可以创建一个流。当然,你必须定义一个mapper函数来从结果集中获取迭代值。
You may create a wrapper for the ResultSet
making it an Iterable
. From there you can iterate as well as create a stream. Of course you have to define a mapper function to get the iterated values from the result set.
ResultSetIterable
可能看起来像这样
public class ResultSetIterable<T> implements Iterable<T> {
private final ResultSet rs;
private final Function<ResultSet, T> onNext;
public ResultSetIterable(ResultSet rs, CheckedFunction<ResultSet, T> onNext){
this.rs = rs;
//onNext is the mapper function to get the values from the resultSet
this.onNext = onNext;
}
private boolean resultSetHasNext(){
try {
hasNext = rs.next();
} catch (SQLException e) {
//you should add proper exception handling here
throw new RuntimeException(e);
}
}
@Override
public Iterator<T> iterator() {
try {
return new Iterator<T>() {
//the iterator state is initialized by calling next() to
//know whether there are elements to iterate
boolean hasNext = resultSetHasNext();
@Override
public boolean hasNext() {
return hasNext;
}
@Override
public T next() {
T result = onNext.apply(rs);
//after each get, we need to update the hasNext info
hasNext = resultSetHasNext();
return result;
}
};
} catch (Exception e) {
//you should add proper exception handling here
throw new RuntimeException(e);
}
}
//adding stream support based on an iteratable is easy
public Stream<T> stream() {
return StreamSupport.stream(this.spliterator(), false);
}
}
现在我们有了包装器,你可以流过结果:
Now that we have our wrapper, you could stream over the results:
ResultSet rs = stmt.executeQuery();
List<String> userIdList = new ResultSetIterable(rs, rs -> rs.getString(1)).stream()
.collect(Collectors.toList())
}
正如Lukas指出的那样, rs.getString(1)
可能会抛出一个已检查的 SQLException
,因此我们需要使用 CheckedFunction
而不是java Function
,它能够在未经检查的Exception中包装任何已检查的Exception。
一个非常简单的实现可能是
As Lukas pointed out, the rs.getString(1)
may throw a checked SQLException
, therefor we need to use a CheckedFunction
instead of a java Function
that would be capable of wrapping any checked Exception in an unchecked one.
A very simple implementation could be
public interface CheckedFunction<T,R> extends Function<T,R> {
@Override
default R apply(T t) {
try {
return applyAndThrow(t);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
R applyAndThrow(T t) throws Exception;
}
Alternatively you could use a library with such a function, i.e. jooλ or vavr
这篇关于Java Streams迭代ResultSet对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!