Java8 流 collectors.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 throwing 函数改编为通用的 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() 方法可以 return 为 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(); 
    }
}