繁体   English   中英

列出<Object []>到java 8中的Map <K,V>

[英]List<Object[]> to Map<K, V> in java 8

通常需要为以下查询转换结果:

select category, count(*)
from table
group by category

到一个映射,其中键是类别,值是属于同一类别的记录的数量。

许多持久性框架返回像List<Object[]>这样的查询的结果,其中对象数组包含两个元素(类别和每个返回结果集行的计数)。

我试图找到最可读的方式将此列表转换为相应的地图。

当然,传统方法包括创建地图并手动输入条目:

Map<String, Integer> map = new HashMap<>();
list.stream().forEach(e -> map.put((String) e[0], (Integer) e[1]));

我想到的第一个单线程是利用开箱即用的Collectors.toMap收集器:

Map<String, Integer> map = list.stream().collect(toMap(e -> (String) e[0], e -> (Integer) e[1]));

但是,我发现这种e -> (T) e[i]语法比传统方法的可读性稍差。 为了解决这个问题,我可以创建一个util方法,我可以在所有这些情况下重用它:

public static <K, V> Collector<Object[], ?, Map<K, V>> toMap() {
  return Collectors.toMap(e -> (K) e[0], e -> (V) e[1]);
}

然后我有一个完美的单行:

Map<String, Integer> map = list.stream().collect(Utils.toMap());

由于类型推断,甚至不需要转换键和值。 但是,对于代码的其他读者(在util方法签名中的Collector<Object[], ?, Map<K, V>>等),这有点难以理解。

我想知道,java 8工具箱中还有什么可以帮助以更可读/更优雅的方式实现这一目标吗?

我认为你现在的'单线'很好。 但是,如果您不特别喜欢命令中内置的魔术索引,那么您可以封装在枚举中:

enum Column {
    CATEGORY(0), 
    COUNT(1);

    private final int index;

    Column(int index) {
        this.index = index;
    }

    public int getIntValue(Object[] row) {
        return (int)row[index]);
    }

    public String getStringValue(Object[] row) {
        return (String)row[index];
    }
}

然后你的提取代码变得更清晰了:

list.stream().collect(Collectors.toMap(CATEGORY::getStringValue, COUNT::getIntValue));

理想情况下,您需要向列添加类型字段并检查是否调用了正确的方法。

虽然不在您的问题范围内,但理想情况下,您将创建一个表示封装查询的行的类。 类似下面的内容(为了清晰起见,跳过了吸气剂):

class CategoryCount {
    private static final String QUERY = "
        select category, count(*) 
        from table 
        group by category";

    private final String category;
    private final int count;

    public static Stream<CategoryCount> getAllCategoryCounts() {
        list<Object[]> results = runQuery(QUERY);
        return Arrays.stream(results).map(CategoryCount::new);
    }

    private CategoryCount(Object[] row) {
        category = (String)row[0];
        count = (int)row[1];
    }
}

这将查询和行解码之间的依赖关系放入同一个类中,并隐藏用户的所有不必要的细节。

然后创建地图变为:

Map<String,Integer> categoryCountMap = CategoryCount.getAllCategoryCounts()
    .collect(Collectors.toMap(CategoryCount::getCategory, CategoryCount::getCount));

我没有隐藏类强制转换,而是提供了几个函数来帮助提高可读性:

Map<String, Integer> map = results.stream()
        .collect(toMap(
                columnToObject(0, String.class),
                columnToObject(1, Integer.class)
        ));

完整示例:

package com.bluecatcode.learning.so;

import com.google.common.collect.ImmutableList;

import java.util.List;
import java.util.Map;
import java.util.function.Function;

import static java.lang.String.format;
import static java.util.stream.Collectors.toMap;

public class Q35689206 {

    public static void main(String[] args) {
        List<Object[]> results = ImmutableList.of(
                new Object[]{"test", 1}
        );

        Map<String, Integer> map = results.stream()
                .collect(toMap(
                        columnToObject(0, String.class),
                        columnToObject(1, Integer.class)
                ));

        System.out.println("map = " + map);
    }

    private static <T> Function<Object[], T> columnToObject(int index, Class<T> type) {
        return e -> asInstanceOf(type, e[index]);
    }

    private static <T> T asInstanceOf(Class<T> type, Object object) throws ClassCastException {
        if (type.isAssignableFrom(type)) {
            return type.cast(object);
        }
        throw new ClassCastException(format("Cannot cast object of type '%s' to '%s'",
                object.getClass().getCanonicalName(), type.getCanonicalName()));
    }
}

如何转换列表<object>至 Map<k, v> 使用 java stream<div id="text_translate"><p> 我想将List&lt;ObjectInList&gt;转换为Map&lt;K, V&gt;</p><pre> class ObjectInList { List&lt;Long&gt; listWithLong; Map&lt;String, Object&gt; dataMap; // there is 'id' key, and i want to use this id as key in map to be converted }</pre><p> 新的 map 格式如下</p><pre>String type; // this type is value of dataMap. List&lt;Long&gt; contents</pre><p> List&lt;Object&gt;中的每个 Object 都可以有重复的类型</p><p>例如</p><pre>///////// before converted //////////// [ { list: [1,2,3], dataMap: { type: "a", } }, { list: [4,5,6], dataMap: { type: "b", } }, { list: [7,8], dataMap: { type: "a", } }, ] ///////////// after converted ////////// { "a": [1,2,3,7,8], "b": [4,5,6] }</pre></div></k,></object>

[英]How to convert LIst<Object> to Map<K, V> with using java stream

Java 8 转换一个List<object> 至 Map<k,v> 使用对象的孩子的领域?<div id="text_translate"><p> 情况很简单:我有一个 object List&lt;ParentClass&gt; list并想将其转换为Map&lt;orderKey, price&gt;</p><p> class 如下所示</p><pre>class ParentClass{ Child1Class a; Child2Class b; }</pre><p> orderKey class 看起来像这样</p><pre>class orderKey{ String id; String itemName; }</pre><p> 儿童班是这样的</p><pre>class Child1Class{ String id; String itemName; Date date; ..... } class Child2Class{ BigDecimal price; .... }</pre><p> 所有的类都有对应每个字段的 getter 和 setter。 所以我本质上是想 map 孩子们的领域。 我怎样才能做到这一点?</p><pre> -----------------------------MY ATTEMPT IS SOMETHING LIKE THIS-------------------------------------- list.stream(). .collect(Collectors.toMap(ParentClass::getA, ParentClass::getB).entrySet().stream()...... then I'm stuck</pre><p> 不知道如何构建临时 object orderKey作为新 map 的密钥。 任何帮助,将不胜感激。</p></div></k,v></object>

[英]Java 8 convert a List<Object> to Map<K,V> using the fields of the object's children?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 转换清单 <Object> 到地图 <K,V> 在java中 Java 8转换地图 <K, List<V> &gt;到地图 <V, List<K> &gt; 如何转换列表<object>至 Map<k, v> 使用 java stream<div id="text_translate"><p> 我想将List&lt;ObjectInList&gt;转换为Map&lt;K, V&gt;</p><pre> class ObjectInList { List&lt;Long&gt; listWithLong; Map&lt;String, Object&gt; dataMap; // there is 'id' key, and i want to use this id as key in map to be converted }</pre><p> 新的 map 格式如下</p><pre>String type; // this type is value of dataMap. List&lt;Long&gt; contents</pre><p> List&lt;Object&gt;中的每个 Object 都可以有重复的类型</p><p>例如</p><pre>///////// before converted //////////// [ { list: [1,2,3], dataMap: { type: "a", } }, { list: [4,5,6], dataMap: { type: "b", } }, { list: [7,8], dataMap: { type: "a", } }, ] ///////////// after converted ////////// { "a": [1,2,3,7,8], "b": [4,5,6] }</pre></div></k,></object> Java 8 列表<V>进入地图<K, V>带功能 Java 8 列表<V>进入地图<K, V> Java 8 列表<String>进入地图<String, K>其中 K 是一个在其构造函数中需要 V 的新对象 Java 8 流映射<K,V>列出<T> Java 8将<T>列入Map <K,V> Java 8 转换一个List<object> 至 Map<k,v> 使用对象的孩子的领域?<div id="text_translate"><p> 情况很简单:我有一个 object List&lt;ParentClass&gt; list并想将其转换为Map&lt;orderKey, price&gt;</p><p> class 如下所示</p><pre>class ParentClass{ Child1Class a; Child2Class b; }</pre><p> orderKey class 看起来像这样</p><pre>class orderKey{ String id; String itemName; }</pre><p> 儿童班是这样的</p><pre>class Child1Class{ String id; String itemName; Date date; ..... } class Child2Class{ BigDecimal price; .... }</pre><p> 所有的类都有对应每个字段的 getter 和 setter。 所以我本质上是想 map 孩子们的领域。 我怎样才能做到这一点?</p><pre> -----------------------------MY ATTEMPT IS SOMETHING LIKE THIS-------------------------------------- list.stream(). .collect(Collectors.toMap(ParentClass::getA, ParentClass::getB).entrySet().stream()...... then I'm stuck</pre><p> 不知道如何构建临时 object orderKey作为新 map 的密钥。 任何帮助,将不胜感激。</p></div></k,v></object> 转换清单 <V> 在地图上 <K,V> 与流Java 8
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM