关于java:实战小技巧19List转Map-List的几种姿势

38次阅读

共计 3167 个字符,预计需要花费 8 分钟才能阅读完成。

明天介绍一个实用的小知识点,如何将 List 转为Map<Object, List<Object>>

<!– more –>

1. 根本写法

最开始介绍的当然是最常见、最直观的写法,当然也是任何限度的写法

// 比方将上面的列表,依照字符串长度进行分组
List<String> list = new ArrayList<>();
list.add("hello");
list.add("word");
list.add("come");
list.add("on");
Map<Integer, List<String>> ans = new HashMap<>();

for(String str: list) {List<String> sub = ans.get(str.length());
    if(sub == null) {sub = new ArrayList<>();
        ans.put(str.length(), sub);
    }
    sub.add(str);
}
System.out.println(ans);

对于 jdk8+,下面 for 循环中的内容能够利用 Map.computeIfAbsent 来替换,具体写法如下

for (String str : list) {ans.computeIfAbsent(str.length(), k -> new ArrayList<>()).add(str);
}

当然既然曾经是 jdk1.8 了,借助 Stream 的流解决,能够将下面的更一步进行简化,如下

Map<Integer, List<String>> ans = list.stream().collect(Collectors.groupingBy(String::length));

2. 通用办法

下面是针对特定的列表,针对业务进行开发转换,那么咱们接下来尝试构建一个通用的工具类

这里咱们次要借助的知识点就是泛型,一个重要的点就是如何获取 Map 中的 key

对于 jdk < 1.8 的写法,通过接口来定义实现 key 的获取姿态

public static <K, V> Map<K, List<V>> toMapList(List<V> list, KeyFunc<V, K> keyFunc) {Map<K, List<V>> result = new HashMap<>();
    for (V item: list) {K key = keyFunc.getKey(item);
        if (!result.containsKey(key)) {result.put(key, new ArrayList<>());
        }
        result.get(key).add(item);
    }
    return result;
}

public static interface KeyFunc<T, K> {K getKey(T t);
}

应用 demo 如下

public static void main(String[] args) {List<String> list = new ArrayList<>();
    list.add("hello");
    list.add("word");
    list.add("come");
    list.add("on");
    Map<Integer, List<String>> res = toMapList(list, new KeyFunc<String, Integer>() {
        @Override
        public Integer getKey(String s) {return s.length();
        }
    });
    System.out.println(res);
}

接下来再看一下 jdk1.8 之后的写法,联合 stream + 函数办法来实现

public static <K, V> Map<K, List<V>> toMapList(List<V> list, Function<V, K> func) {return list.stream().collect(Collectors.groupingBy(func));
}

其对应的应用形式则如下

public static void main(String[] args) {List<String> list = new ArrayList<>();
    list.add("hello");
    list.add("word");
    list.add("come");
    list.add("on");
    Map<Integer, List<String>> res = toMapList(list, (Function<String, Integer>) String::length);
    System.out.println(res);
}
  1. 工具类

上一节介绍了基于泛型 + jdk8 Stream + 函数办法来实现通用转换工具类的实现姿态,接下来咱们小结一下,输入一个实用于 1.8 之后的工具类

/**
 * List<V> 转换为 Map<K, List<V>> 特点在于 Map 中的 value,是个列表,且列表中的元素就是从原列表中的元素
 *
 * @param list
 * @param func 基于 list#item 生成 Map.key 的函数办法
 * @param <K>
 * @param <V>
 * @return
 */
public static <K, V> Map<K, List<V>> toMapList(List<V> list, Function<V, K> func) {return list.stream().collect(Collectors.groupingBy(func));
}

/**
 * List<I> 转换为 Map<K, List<V>> 特点在于 Map 中的 value 是个列表,且列表中的元素是由 list.item 转换而来
 *
 * @param list
 * @param keyFunc 基于 list#item 生成的 Map.key 的函数办法
 * @param valFunc 基于 list#item 转换 Map.value 列表中元素的函数办法
 * @param <K>
 * @param <I>
 * @param <V>
 * @return
 */
public static <K, I, V> Map<K, List<V>> toMapList(List<I> list, Function<I, K> keyFunc, Function<I, V> valFunc) {return list.stream().collect(Collectors.groupingBy(keyFunc, Collectors.mapping(valFunc, Collectors.toList())));
}

4.guava HashMultimap 扩大知识点

最初再介绍一个扩大知识点,Gauva 工具包中提供了一个 HashMultimap 的工具类,他的应用姿态和咱们平时的 Map 并无差别,然而须要在留神的是,它的 value 是个汇合

List<String> list = new ArrayList<>();
list.add("hello");
list.add("word");
list.add("come");
list.add("on");
list.add("on");
HashMultimap<Integer, String> map = HashMultimap.create();
for (String item: strList) {map.put(item.length(), item);
}
System.out.println(map);

理论输入如下,验证了 value 实际上是个汇合(on 只有一个,如果是咱们下面的工具类,会输入两个)

{2=[on], 4=[word, come], 5=[hello]}

一灰灰的联系方式

尽信书则不如无书,以上内容,纯属一家之言,因集体能力无限,不免有疏漏和谬误之处,如发现 bug 或者有更好的倡议,欢送批评指正,不吝感谢

  • 集体站点:https://blog.hhui.top
  • 微博地址: 小灰灰 Blog
  • QQ:一灰灰 /3302797840
  • 微信公众号:一灰灰 blog

正文完
 0