Java8流收集器.ToMap方法参考失败

问题描述

有人可以告诉我以下示例代码中的问题是什么。 为了举例说明,我们可以假设resultSet中所有列均可用,并且所有内容均为String。

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

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在their answer中所示,您可以将for循环与try/catch块一起使用来处理您的情况。或者,如果您想坚持使用更具功能性的方法,则可以声明自己的功能接口,该接口将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方法可以返回null,因此鼓励使用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(); 
    }
}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...