Не удается преобразовать список кортежей в hashmap java

#java #hashmap #tuples

#java #hashmap #кортежи

Вопрос:

Я хочу преобразовать javax.persistence.Tuple в HashMap , но вот так, он вставляет последний элемент кортежа и принимает также псевдоним и тип данных. Как я могу улучшить этот метод, чтобы он принимал значения кортежа?

 public Map<String, Object> tuplesToMap(List<Tuple> data){
    Map<String, Object> values = new HashMap<>();
    data.forEach(tuple -> {
        tuple.getElements().forEach(
            element -> {
                values.put(element.getAlias(), tuple.get(element));
            }
        );
    });
    return values;
}
  

Комментарии:

1. вы говорите о javax.persistence. Кортеж, не так ли?

2. @luca.vercelli да

Ответ №1:

с Java 8 просто :

 return data.stream()
    .collect(Collectors.toMap(
        t -> t.get(0, String.class),
        t -> t.get(1, Object.class)));
  

Ответ №2:

Кажется, работает :

 public static List<Map<String/*UPPERCASE*/, Object>> jpaTuplesToMaps(
  List<javax.persistence.Tuple> data
){
    return data.stream()
        .map(tuple -> { // per each tuple of the input List
            // creating a new HashMap
            Map<String, Object> resultItem =  new HashMap<>();
            // filling the created HashMap with values of
            tuple.getElements().forEach( // each column of the tuple
                col -> { resultItem.put(col.getAlias(), tuple.get(col)); } 
            );
            // returning the created HashMap instead of  the current Tuple
            return resultItem;
        })
         // collecting amp; returning all the created HashMap-s as a List
        .collect(Collectors.toList());
}
  

Но обычно требуются преобразования как отдельных элементов, так и списка, поэтому давайте объединим их :

 public static Map<String/*UPPERCASE*/, Object> jpaTupleToMap(
    javax.persistence.Tuple data /*CASE INSENSITIVE*/
){
    Map<String, Object> result = 
        new HashMap<>(); // exactly HashMap since it can handle NULL keys amp; values
    data.getElements().forEach(
        col -> { result.put(col.getAlias(), data.get(col)); } 
    );
    return resu<
}

//-------------------------
    
public static List<Map<String/*UPPERCASE*/, Object>> jpaTuplesToMaps(
    List<javax.persistence.Tuple> data /*CASE INSENSITIVE*/
){
    return data.stream() // List<Tuple> -> Tuple1,..TupleN
        .map(tuple -> jpaTupleToMap(tuple)) // Tuple1 -> HashMap1,..TupleN -> HashMapN
        .collect(Collectors.toList()); // HashMap1,..HashMapN -> List
}

  

Ответ №3:

element.getAlias() Вы используете в качестве ключа для hashmap, вероятно, то же самое для некоторых элементов.

Map ключи уникальны, что означает, что если вы вставляете записи (1, «один»), а затем (1, «два»), первое значение будет переопределено последним. Если вы хотите, чтобы несколько значений были сопоставлены одному ключу, используйте Map<String, Collection<Object>> или Multimap из Guava, что в точности одно и то же.

Вы можете вставить в multimap с помощью этой функции — если ключа нет в карте, создайте новый ArrayList и добавьте его на карту, в противном случае верните существующий. Затем вставьте значение в список:

 values
    .computeIfAbsent(element.getAlias, k -> new ArrayList<>())
    .add(tuple.get(element));
  

Комментарии:

1. Если я сделаю это таким образом, я получу несовместимый тип для tuple.get (element)

2. Да, вам также необходимо создать коллекцию, в которую вы поместили элементы — вы изменили значения в карте с Object на Collection<Object>

3. Вы, конечно, можете это сделать, в этом случае у вас было бы List<Map<String, Object>> вместо Map<String, List<Object>> — просто имейте в виду, что ключи карты уникальны, и вам решать, не перезаписывать ли существующее отображение.

4. Я согласен с @OndraK. Я просто понимаю, что List<Tuple> на самом деле является матрицей или также таблицей. Поэтому нецелесообразно преобразовывать его в Map<String, Object> , который представляет собой одну строку таблицы. Разумнее преобразовать его в List<Map<String, Object>> .