Java Streams迭代ResultSet对象 [英] Java Streams to iterate over a ResultSet object

查看:133
本文介绍了Java Streams迭代ResultSet对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码片段

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 将其设为 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;
}

或者你可以使用具有这种功能的库,即jooλ vavr

Alternatively you could use a library with such a function, i.e. jooλ or vavr

这篇关于Java Streams迭代ResultSet对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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