[SonarLint]: сделать этот анонимный внутренний класс лямбдой
Приведенный ниже код работает, но у меня есть уведомление от SonarLint, потому что я использую анонимный класс в потоке вместо лямбда-выражения, и я не вижу, как улучшить приведенный ниже код, избегая уведомления:
Properties prop = new Properties();
Properties temp = new Properties();
//... add some values and keys in prop and temp
prop.putAll(temp.entrySet().stream()
.filter( entry -> !prop.containsKey(entry.getKey()))
.map( new Function<Entry<Object, Object>, Entry<String, String>>(){
@Override
public Entry<String, String> apply(Entry<Object, Object> entry) {
return new Entry<String, String>() {
@Override
public String setValue(String value) {
return value.trim().toLowerCase();
}
@Override
public String getValue() {
return ((String) entry.getValue()).trim().toLowerCase();
}
@Override
public String getKey() {
return ((String) entry.getKey()).trim().toLowerCase();
}
};
}
})
.collect(Collectors.toMap(Entry<String,String>::getKey, Entry<String,String>::getValue)));
Объяснение кода: я использую класс свойств из java.util и, к сожалению, entrySet
свойств возвращается Entry<Object, Object>
не Entry<String, String>
, Я хочу "соединить" два объекта свойств, указав ключ и значение в нижнем регистре. Итак, карта позволяет конвертировать Entry<Object, Object>
в Entry<String,String>
, Вот почему, есть анонимный класс.
1 ответ
Сонар предлагает заменить
prop.putAll(temp.entrySet().stream()
.filter( entry -> !prop.containsKey(entry.getKey()))
.map( new Function<Entry<Object, Object>, Entry<String, String>>(){
@Override
public Entry<String, String> apply(Entry<Object, Object> entry) {
return new Entry<String, String>() {
@Override
public String setValue(String value) {
return value.trim().toLowerCase();
}
@Override
public String getValue() {
return ((String) entry.getValue()).trim().toLowerCase();
}
@Override
public String getKey() {
return ((String) entry.getKey()).trim().toLowerCase();
}
};
}
})
.collect(Collectors.toMap(Entry::getKey, Entry::getValue)));
(Я удалил ненужные аргументы типа в коллекторе)
с
prop.putAll(temp.entrySet().stream()
.filter( entry -> !prop.containsKey(entry.getKey()))
.map(entry -> new Entry<String, String>() {
@Override
public String setValue(String value) {
return value.trim().toLowerCase();
}
@Override
public String getValue() {
return ((String) entry.getValue()).trim().toLowerCase();
}
@Override
public String getKey() {
return ((String) entry.getKey()).trim().toLowerCase();
}
})
.collect(Collectors.toMap(Entry::getKey, Entry::getValue)));
который использует лямбда-выражение в качестве замены для реализации анонимного внутреннего класса Function
не для Entry
реализация.
Тем не менее, нет смысла реализовывать Entry
интерфейс вручную здесь, особенно не с фактически нежелательным setValue
Метод в этом договоре нарушает путь. Вы хотите только неизменный Entry
Таким образом, вы можете создать экземпляр существующего класса:
prop.putAll(temp.entrySet().stream()
.filter( entry -> !prop.containsKey(entry.getKey()))
.map(entry -> new AbstractMap.SimpleImmutableEntry<>(
((String) entry.getKey()).trim().toLowerCase(),
((String) entry.getValue()).trim().toLowerCase()))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue)));
как последнее улучшение, вы можете избавиться от Entry
Например, при выполнении преобразования в функции, переданные toMap
коллектор:
prop.putAll(temp.entrySet().stream()
.filter( entry -> !prop.containsKey(entry.getKey()))
.collect(Collectors.toMap(
entry -> ((String) entry.getKey()) .trim().toLowerCase(),
entry -> ((String) entry.getValue()).trim().toLowerCase())));