Usng StringJoiner в сложных HashMaps - PullRequest
3 голосов
/ 16 мая 2019

У меня есть список карт, как показано ниже:

List<Map<String,Object>> someObjectsList = new ArrayList<Map<String,Object>>();

Я храню следующие данные в каждой хэш-карте

key             value
2017-07-21      2017-07-21-07.33.28.429340
2017-07-24      2017-07-24-01.23.33.591340
2017-07-24      2017-07-24-01.23.33.492340
2017-07-21      2017-07-21-07.33.28.429540

Я хочу перебрать список HashMap s и проверить, совпадает ли ключ с первыми 10 символами любого из значений HashMap, затем я хочу сохранить эти ключи и значения в следующем формате. то есть с помощью телеметра «запятая». Конечная цель - сгруппировать уникальные ключи HashMaps и их относительные значения (если ключ совпадает с первыми 10 символами любого из значений HashMap) в новом HashMap.

key          value
2017-07-21  2017-07-21-07.33.28.429340,2017-07-21-07.33.28.429540
2017-07-24  2017-07-24-01.23.33.591340,2017-07-24-01.23.33.492340

Я пытаюсь использовать следующий код Java, используя StringJoiner, но не получаю ожидаемых результатов. Любая подсказка о том, как создать здесь логику?

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;

public class SampleOne {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        List<Map<String, Object>> someObjectsList = new ArrayList<Map<String, Object>>();

        Map<String, Object> mapOne = new HashMap<String, Object>();
        mapOne.put("2017-07-21", "2017-07-21-07.33.28.429340");

        Map<String, Object> mapTwo = new HashMap<String, Object>();
        mapTwo.put("2017-07-24", "2017-07-24-01.23.33.591340");

        Map<String, Object> mapThree = new HashMap<String, Object>();
        mapThree.put("2017-07-24", "2017-07-24-01.23.33.492340");

        Map<String, Object> mapFour = new HashMap<String, Object>();
        mapFour.put("2017-07-21", "2017-07-21-07.33.28.429540");

        someObjectsList.add(mapOne);
        someObjectsList.add(mapTwo);
        someObjectsList.add(mapThree);
        someObjectsList.add(mapFour);

        for (Map map : someObjectsList) {
            StringJoiner sj = new StringJoiner(",");
            for (Object key : map.keySet()) {
                String value = ((String) map.get(key));
                String date = value.substring(0, Math.min(value.length(), 10));
                //System.out.println(str);
                //System.out.println(value);

                if(key.equals(date)) {
                    sj.add(value);
                    System.out.println(sj.toString());
                }
            }

        }

    }

}

выход:

2017-07-21-07.33.28.429340
2017-07-24-01.23.33.591340
2017-07-24-01.23.33.492340
2017-07-21-07.33.28.429540

Ответы [ 4 ]

1 голос
/ 16 мая 2019

Вы ищете группирование поведения обработки List.Вы можете использовать преимущество , поскольку .В любом случае вам нужен новый Map для хранения значений, чтобы их напечатать.:

someObjectsList.stream()
        .flatMap(i -> i.entrySet().stream())               // flatmapping to entries
        .collect(Collectors.groupingBy(Entry::getKey))     // grouping them using the key

Если вы хотите использовать циклы for.В этом случае это сложнее, поскольку в каждом элементе списка может появиться больше записей:

final Map<String, List<Object>> map = new HashMap<>();
for (Map<String, Object> m: someObjectsList) {          // iterate List<Map>
    for (Entry<String, Object> entry: m.entrySet()) {   // iterate entries of each Map
        List<Object> list;
        final String key = entry.getKey();              // key of the entry
        final Object value = entry.getValue();          // value of the entry
        if (map.containsKey(key)) {                     // if the key exists
            list = map.get(key);                        // ... use it
        } else {
            list = new ArrayList<>();                   // ... or else create a new one
        }
        list.add(value);                                // add the new value
        map.put(key, list);                             // and add/update the entry
    }
}

Печать из Map<String, List<Object>> map в обоих случаях приведет к следующему выводу:

2017-07-21=[2017-07-21-07.33.28.429340, 2017-07-21-07.33.28.429540], 
2017-07-24=[2017-07-24-01.23.33.591340, 2017-07-24-01.23.33.492340]
1 голос
/ 16 мая 2019

По какой причине вы используете Object вместо String и избегаете проверок безопасности? Тем не менее, это не «первые 10 символов», вы хотите увидеть, начинается ли value с key точка останова (все ваши ключи состоят из 10 символов). Так что в этом случае вы можете просто сделать if (value.startsWith(key)) { ... }. Не забывайте свои новые строки, если струнный не был полон. Наконец, вам не нужен List, Map может одновременно удерживать несколько клавиш. Альтернативный способ сделать это:

//LinkedHashMap will preserve our insertion order
Map<String, String> map = new LinkedHashMap<>();
map.put("2017-07-21", "2017-07-21-07.33.28.429340");
map.put("2017-07-24", "2017-07-24-01.23.33.591340");
//note duplicates are overwritten, but no value change here
map.put("2017-07-24", "2017-07-24-01.23.33.492340");
map.put("2017-07-21", "2017-07-21-07.33.28.429540");
//  You can also use Java 8 streams for the concatenation
//  but I left it simple
List<String> matches = map.entrySet()
        .filter(e -> e.getValue().startsWith(e.getKey())
        .collect(Collectors.toList());
String concatenated = String.join("\n", matches);

Если вы хотите сгенерировать эту строку без потоков, она будет выглядеть следующим образом (опять же, для простоты не используется #entrySet, но здесь это будет более эффективно):

List<String> matches = new ArrayList<>();
StringJoiner joiner = new StringJoiner("\n");
for (String key : map.keySet()) {
    String value = map.get(key);
    if (value.startsWith(key)) {
        joiner.add(value);
    }
}
//joiner#toString will give the expected result
1 голос
/ 16 мая 2019

Используйте функцию .merge :

Map<String, Object> finalMap = new HashMap<String, Object>();

for (Map map : someObjectsList) {
    for (Object key : map.keySet()) {
        String value = ((String) map.get(key));
        finalMap.merge((String) key, value, (k, v) -> k + "," + v);
    }
}

, которая выводит:

{2017-07-21 = 2017-07-21-07.33.28.429340,2017-07-21-07.33.28.429540, 2017-07-24 = 2017-07-24-01.23.33.591340,2017-07-24-01.23.33.492340}


То же самое может быть достигнуто с помощью следующей однострочной:

someObjectsList.stream()
               .flatMap(i -> i.entrySet().stream())
               .collect(Collectors.toMap(Entry::getKey, Entry::getValue, 
                                        (k, v) -> k + "," + v));
1 голос
/ 16 мая 2019

В вашем коде вы используете разные StringJoiner на каждой карте. Итак, он создает новый экземпляр этого.

Вы можете сохранить свои ключи на карте. Пример кода: (Изменить: я не удалил вашу часть StringJoiner.)

public static void main(String[] args) {
        // TODO Auto-generated method stub
        List<Map<String, Object>> someObjectsList = new ArrayList<Map<String, Object>>();

        Map<String, Object> mapOne = new HashMap<String, Object>();
        mapOne.put("2017-07-21", "2017-07-21-07.33.28.429340");

        Map<String, Object> mapTwo = new HashMap<String, Object>();
        mapTwo.put("2017-07-24", "2017-07-24-01.23.33.591340");

        Map<String, Object> mapThree = new HashMap<String, Object>();
        mapThree.put("2017-07-24", "2017-07-24-01.23.33.492340");

        Map<String, Object> mapFour = new HashMap<String, Object>();
        mapFour.put("2017-07-21", "2017-07-21-07.33.28.429540");

        someObjectsList.add(mapOne);
        someObjectsList.add(mapTwo);
        someObjectsList.add(mapThree);
        someObjectsList.add(mapFour);

        Map<String, Object> outputMap = new HashMap<String, Object>();

        for (Map map : someObjectsList) {
            StringJoiner sj = new StringJoiner(",");
            for (Object key : map.keySet()) {
                String value = ((String) map.get(key));
                String date = value.substring(0, Math.min(value.length(), 10));
                //System.out.println(str);
                //System.out.println(value);

                if(key.equals(date)) {
                    sj.add(value);
                    System.out.println(sj.toString());
                    if(outputMap.containsKey(key)) {
                        String str = (String) map.get(key);
                        str = str + "," + value;
                        outputMap.put((String)key, str);
                    } else {
                        outputMap.put((String)key, value);
                    }
                }
            }
        }

        for (String map : outputMap.keySet()) {
             System.out.println(map + " " + outputMap.get(map));
        }
    }
...