簡體   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