概述

介绍

Iterator相关帮助类

集合包中封装了包括Enumeration、Iterator等的包装,这包括:

  • ArrayIterator 数组Iterator,便于数组利用Iterator方式遍历
  • CopiedIterator 为了解决并发情况下Iterator遍历导致的问题而封装的Iterator
  • EnumerationIterator Enumeration的Iterator表现形式
  • IteratorEnumeration Iterator的Enumeration表现形式

同时提供了IterUtil工具和CollUtil工具类用于简化对Iterator和集合的操作。

集合工具-CollUtil

介绍

这个工具主要增加了对数组、集合类的操作。

1. join 方法

将集合转换为字符串,这个方法还是挺常用,是StrUtil.split的反方法。这个方法的参数支持各种类型对象的集合,最后连接每个对象时候调用其toString()方法。栗子如下:

  1. String[] col= new String[]{"a","b","c","d","e"};
  2. List<String> colList = CollUtil.newArrayList(col);
  3. String str = CollUtil.join(colList, "#"); //str -> a#b#c#d#e

2. sortPageAllsortPageAll2方法

这个方法其实是一个真正的组合方法,功能是:将给定的多个集合放到一个列表(List)中,根据给定的Comparator对象排序,然后分页取数据。这个方法非常类似于数据库多表查询后排序分页,这个方法存在的意义也是在此。sortPageAll2功能和sortPageAll的使用方式和结果是 一样的,区别是sortPageAll2使用了BoundedPriorityQueue这个类来存储组合后的列表,不知道哪种性能更好一些,所以就都保留了。使用此方法,栗子如下:

  1. //Integer比较器
  2. Comparator<Integer> comparator = new Comparator<Integer>(){
  3. @Override
  4. public int compare(Integer o1, Integer o2) {
  5. return o1.compareTo(o2);
  6. }
  7. };
  8. //新建三个列表,CollUtil.newArrayList方法表示新建ArrayList并填充元素
  9. List<Integer> list1 = CollUtil.newArrayList(1, 2, 3);
  10. List<Integer> list2 = CollUtil.newArrayList(4, 5, 6);
  11. List<Integer> list3 = CollUtil.newArrayList(7, 8, 9);
  12. //参数表示把list1,list2,list3合并并按照从小到大排序后,取0~2个(包括第0个,不包括第2个),结果是[1,2]
  13. @SuppressWarnings("unchecked")
  14. List<Integer> result = CollUtil.sortPageAll(0, 2, comparator, list1, list2, list3);
  15. System.out.println(result); //输出 [1,2]

3. sortEntrySetToList方法

这个方法主要是对Entry<Long, Long>按照Value的值做排序,使用局限性较大,我已经忘记哪里用到过了……

4. popPart方法

这个方法传入一个栈对象,然后弹出指定数目的元素对象,弹出是指pop()方法,会从原栈中删掉。

5.newHashMapnewHashSetnewArrayList方法

这些方法是新建相应的数据结构,数据结构元素的类型取决于你变量的类型,例子如下:

  1. HashMap<String, String> map = CollUtil.newHashMap();
  2. HashSet<String> set = CollUtil.newHashSet();
  3. ArrayList<String> list = CollUtil.newArrayList();

6. append方法

在给定数组里末尾加一个元素,其实List.add()也是这么实现的,这个方法存在的意义是只有少量的添加元素时使用,因为内部使用了System.arraycopy,每调用一次就要拷贝数组一次。这个方法也是为了在某些只能使用数组的情况下使用,省去了先要转成List,添加元素,再转成Array。

7. resize方法

重新调整数据的大小,如果调整后的大小比原来小,截断,如果比原来大,则多出的位置空着。(貌似List在扩充的时候会用到类似的方法)

8. addAll方法

将多个数据合并成一个数组

9. sub方法

对集合切片,其他类型的集合会转换成List,封装List.subList方法,自动修正越界等问题,完全避免IndexOutOfBoundsException异常。

10. isEmptyisNotEmpty方法

判断集合是否为空(包括null和没有元素的集合)。

11. zip方法

此方法也是来源于Python的一个语法糖,给定两个集合,然后两个集合中的元素一一对应,成为一个Map。此方法还有一个重载方法,可以传字符,然后给定分分隔符,字符串会被split成列表。栗子:

  1. String[] keys = new String[]{"a", "b", "c"};
  2. Integer[] values = new Integer[]{1, 2, 3};
  3. Map<String, Integer> map = CollUtil.zip(keys,values);
  4. System.out.println(map); // {b=2, c=3, a=1}
  5. String a = "a,b,c";
  6. String b = "1,2,3";
  7. Map<String, String> map2 = CollUtil.zip(a,b, ",");
  8. System.out.println(map2); // {b=2, c=3, a=1}

12. filter方法

此方法可以过滤map,排除不需要的key。栗子:

  1. @Test
  2. public void CollUtil_Filter() {
  3. Map<String, Object> m = new HashMap<String, Object>() {{
  4. put("k1", "v1");
  5. put("k2", "v2");
  6. put("k3", "v3");
  7. }};
  8. String[] inc = {"k1", "k3"};//需要的key
  9. List<String> incList = Arrays.asList(inc);
  10. m = CollectionUtil.filter(m, new Editor<Map.Entry<String, Object>>() {
  11. @Override
  12. public Map.Entry<String, Object> edit(Map.Entry<String, Object> stringObjectEntry) {
  13. if (incList.contains(stringObjectEntry.getKey())) {
  14. return stringObjectEntry;
  15. }
  16. return null;
  17. }
  18. });
  19. log.info("{}", m);
  20. }

结果

  1. {k3=v3, k1=v1}

列表工具-ListUtil

介绍

List在集合中中使用最为频繁,因此新版本的Hutool中针对List单独封装了工具方法。

使用

过滤列表

  1. List<String> a = ListUtil.toLinkedList("1", "2", "3");
  2. // 结果: [edit1, edit2, edit3]
  3. List<String> filter = ListUtil.filter(a, str -> "edit" + str);

获取满足指定规则所有的元素的位置

  1. List<String> a = ListUtil.toLinkedList("1", "2", "3", "4", "3", "2", "1");
  2. // [1, 5]
  3. int[] indexArray = ListUtil.indexOfAll(a, "2"::equals);

其他方法与CollUtil工具类似,很多工具也有重复。

Iterator工具-IterUtil

来源

最早此工具类中的方法是在CollUtil中的,由于经过抽象,因此单独拿出来以适应更广的场景。

方法介绍

  • isEmpty 是否为null或者无元素
  • isNotEmpty 是否为非null或者至少一个元素
  • hasNull 是否有null元素
  • isAllNull 是否全部为null元素
  • countMap 根据集合返回一个元素计数的Map,所谓元素计数就是假如这个集合中某个元素出现了n次,那将这个元素做为key,n做为value
  • join 使用分隔符将集合转换为字符串
  • toMap toMap Entry列表转Map,或者key和value单独列表转Map
  • asIterator Enumeration转Iterator
  • asIterable Iterator转Iterable
  • getFirst 获取列表的第一个元素
  • getElementType 获取元素类型

    有界优先队列-BoundedPriorityQueue

简介

举个例子。我有一个用户表,这个表根据用户名被Hash到不同的数据库实例上,我要找出这些用户中最热门的5个,怎么做?我是这么做的:

  1. 在每个数据库实例上找出最热门的5个
  2. 将每个数据库实例上的这5条数据按照热门程度排序,最后取出前5条

这个过程看似简单,但是你应用服务器上的代码要写不少。首先需要Query N个列表,加入到一个新列表中,排序,再取前5。这个过程不但代码繁琐,而且牵涉到多个列表,非常浪费空间。
于是,BoundedPriorityQueue应运而生。
先看Demo:

  1. /**
  2. * 有界优先队列Demo
  3. * @author Looly
  4. *
  5. */
  6. public class BoundedPriorityQueueDemo {
  7. public static void main(String[] args) {
  8. //初始化队列,设置队列的容量为5(只能容纳5个元素),元素类型为integer使用默认比较器,在队列内部将按照从小到大排序
  9. BoundedPriorityQueue<Integer> queue = new BoundedPriorityQueue<Integer>(5);
  10. //初始化队列,使用自定义的比较器
  11. queue = new BoundedPriorityQueue<>(5, new Comparator<Integer>(){
  12. @Override
  13. public int compare(Integer o1, Integer o2) {
  14. return o1.compareTo(o2);
  15. }
  16. });
  17. //定义了6个元素,当元素加入到队列中,会按照从小到大排序,当加入第6个元素的时候,队列末尾(最大的元素)将会被抛弃
  18. int[] array = new int[]{5,7,9,2,3,8};
  19. for (int i : array) {
  20. queue.offer(i);
  21. }
  22. //队列可以转换为List哦~~
  23. ArrayList<Integer> list = queue.toList();
  24. System.out.println(queue);
  25. }
  26. }

原理非常简单。设定好队列的容量,然后把所有的数据add或者offer进去(两个方法相同),就会得到前5条数据了。

线程安全的HashSet-ConcurrentHashSet

简介

我们知道,JDK提供了线程安全的HashMap:ConcurrentHashMap,但是没有提供对应的ConcurrentHashSet,Hutool借助ConcurrentHashMap封装了线程安全的ConcurrentHashSet。

使用

与普通的HashSet使用一致:

  1. Set<String> set = new ConcurrentHashSet<>();
  2. set.add("a");
  3. set.add("b");

Map

概述

由来

最早Map的相关工具是被包含在CollUtil中的,但是考虑到Map和集合非同一类数据结构,因此独立出来,且Hutool封装了许多自定义的Map类,因此单独成包。

使用

特殊Map

  • CaseInsensitiveMap 忽略大小写的Map,对KEY忽略大小写,get(“Value”)和get(“value”)获得的值相同,put进入的值也会被覆盖
  • CaseInsensitiveLinkedMap 忽略大小写的LinkedHashMap,对KEY忽略大小写,get(“Value”)和get(“value”)获得的值相同,put进入的值也会被覆盖
  • MapBuilder Map创建器,可以链式创建Map
  • MapProxy Map代理类,通过代理包装Map,提供一系列的getXXX方法

    工具

  • MapUtil 提供对Map常用操作的封装

    Map工具-MapUtil

介绍

MapUtil是针对Map的一一列工具方法的封装,包括getXXX的快捷值转换方法。

方法

  • isEmptyisNotEmpty 判断Map为空和非空方法,空的定义为null或没有值
  • newHashMap 快速创建多种类型的HashMap实例
  • createMap 创建自定义的Map类型的Map
  • of 此方法将一个或多个键值对加入到一个新建的Map中,下面是栗子:

    1. Map<Object, Object> colorMap = MapUtil.of(new String[][] {
    2. {"RED", "#FF0000"},
    3. {"GREEN", "#00FF00"},
    4. {"BLUE", "#0000FF"}
    5. });
  • toListMap 行转列,合并相同的键,值合并为列表,将Map列表中相同key的值组成列表做为Map的value,例如传入数据是:

    1. [
    2. {a: 1, b: 1, c: 1}
    3. {a: 2, b: 2}
    4. {a: 3, b: 3}
    5. {a: 4}
    6. ]

    结果为:

    1. {
    2. a: [1,2,3,4]
    3. b: [1,2,3,]
    4. c: [1]
    5. }
  • toMapList 列转行。将Map中值列表分别按照其位置与key组成新的map,例如传入数据:

    1. {
    2. a: [1,2,3,4]
    3. b: [1,2,3,]
    4. c: [1]
    5. }

    结果为:

    1. [
    2. {a: 1, b: 1, c: 1}
    3. {a: 2, b: 2}
    4. {a: 3, b: 3}
    5. {a: 4}
    6. ]
  • joinjoinIgnoreNull 将Map按照给定的分隔符转换为字符串

  • filter 过滤过程通过传入的Editor实现来返回需要的元素内容,这个Editor实现可以实现以下功能:1、过滤出需要的对象,如果返回null表示这个元素对象抛弃 2、修改元素对象,返回集合中为修改后的对象
  • reverse Map的键和值互换
  • sort 排序Map
  • getAny 获取Map的部分key生成新的Map
  • getgetXXX 获取Map中指定类型的值

    双向查找Map-BiMap

介绍

我们知道在Guava中提供了一种特使的Map结构,叫做BiMap,它实现了一种双向查找的功能,即根据key查找value和根据value查找key,Hutool也同样提供此对象。
BiMap要求key和value都不能重复(非强制要求),如果key重复了,后加入的键值对会覆盖之前的键值对,如果value重复了,则会按照不确定的顺序覆盖key,这完全取决于map实现。比如HashMap无序(按照hash顺序),则谁覆盖谁和hash算法有关;如果是LinkedHashMap,则有序,是后加入的覆盖先加入的。

使用

  1. BiMap<String, Integer> biMap = new BiMap<>(new HashMap<>());
  2. biMap.put("aaa", 111);
  3. biMap.put("bbb", 222);
  4. // 111
  5. biMap.get("aaa");
  6. // 222
  7. biMap.get("bbb");
  8. // aaa
  9. biMap.getKey(111);
  10. // bbb
  11. biMap.getKey(222);

可重复键值Map-TableMap

介绍

有时候我们需要键值对一一对应,但是又有可能有重复的键,也可能有重复的值,就像一个2列的表格一样:

key1 value1
key2 value2

因此,Hutool创建了TableMap这类数据结构,通过键值单独建立List方式,使键值对一一对应,实现正向和反向两种查找。
当然,这种Map无论是正向还是反向,都是遍历列表查找过程,相比标准的HashMap要慢,数据越多越慢。

使用

  1. TableMap<String, Integer> tableMap = new TableMap<>(new HashMap<>());
  2. tableMap.put("aaa", 111);
  3. tableMap.put("bbb", 222);
  4. // 111
  5. tableMap.get("aaa");
  6. // 222
  7. tableMap.get("bbb");
  8. // aaa
  9. tableMap.getKey(111);
  10. // bbb
  11. tableMap.getKey(222);
  12. // [111]
  13. tableMap.getValues("aaa");
  14. //[aaa]
  15. tableMap.getKeys(111);