[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>. Ето защо има анонимен клас.


person Nana Ba    schedule 25.07.2017    source източник


Отговори (1)


Sonar предлага замяна

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())));
person Holger    schedule 25.07.2017