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();
}
}
谁能告诉我以下示例代码中的问题所在。 例如,我们可以假设所有列在 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();
}
}