繁体   English   中英

Java8 流收集器.ToMap 方法引用失败

[英]Java8 streams collectors.ToMap Method reference failing

有人可以告诉我以下示例代码中的问题是什么。 例如,我们可以假设 resultSet 中的所有列都可用,并且所有内容都是字符串。

下面代码中的最后一行失败。

ResultSet rs = JdbcTemplate.query(......)

List<String> columnName= <some predefined fixed values> ;


Map<String,String> columnAndValueMap 
                = columnName
                      .stream()
                      .collect(Collectors.toMap(
                                   Function.identity(),
                                   rs::getString)); //Cannot resolve method 'getString'

Collectors.toMap需要一个Function<String, String>作为它的第二个参数(值映射器函数)。

Function<String, String>是一个具有这个单一抽象方法的函数式接口:

String apply(String arg);

但是, ResultSet.getString方法具有以下签名:

String getString(String columnLabel) throws SQLException;

由于SQLException是已检查的异常,它使ResultSet.getString方法与Function.apply方法不兼容,因此您会收到该错误。


正如@vphilipnyc 在他们的回答中所示,您可以使用带有try/catch块的for循环来处理您的场景。 或者,如果您想坚持使用更函数式的方法,您可以声明自己的函数式接口,将SQLException抛出函数调整为通用java.util.function.Function (通过继承):

@FunctionalInterface
public interface SQLFunction<T, R> extends Function<T, R> {

    R applySQL(T t) throws SQLException;

    @Override
    default R apply(T t) {
        try {
            return applySQL(t);
        } catch (SQLException e) {
            throw new RuntimeException(e); // or your own unchecked exception
        }
    }

    static <T, R> Function<T, R> adapt(SQLFunction<T, R> f) {
        return f;
    }
}

然后,你可以这样使用它:

Map<String, String> columnAndValueMap = columnName.stream()
    .collect(Collectors.toMap(
        Function.identity(),
        SQLFunction.adapt(rs::getString)));

正如@fps 所提到的, rs.getString()方法会按照其签名中的描述抛出 SQLException。

假设您正在寻求创建一个以列名作为键和结果集字符串作为值的映射,您可以执行以下操作:

List<String> columnNames = List.of("columnA", "columnB");

Map<String, Object> map = columnNames.stream().collect(
        Collectors.toMap(Function.identity(), s -> {
            try {
                return Optional.ofNullable(rs.getString(s));
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            return s;
        }));

这有点混乱,因为您需要在流操作期间捕获SQLException 此外,鼓励的做法是使用Optional因为getString()方法可以返回 null。 (理解您假设不会有空值。您的 IDE 可能会突出显示缺少Optional作为警告。)

相反,您最好使用简单的 for 循环并用 try/catch 包围它:

Map<String, String> map = new HashMap<>(columnNames.size());
for (String columnName : columnNames) {
    try {
        map.put(columnName, rs.getString(columnName));
    } catch (SQLException throwables) {
        throwables.printStackTrace(); 
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM