常用hutool和guava的集合工具类总结

Maven

        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>28.0-jre</version>
        </dependency>
        
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.1.0</version>
        </dependency>        

Collections

1.反转指定列表中元素的顺序

 public static void reverse(List<?> list)

2.随机排列集合

public static void shuffle(List<?> list)

3.交换指定位置的集合

 public static void swap(List<?> list, int i, int j)

4.用指定的元素替换指定列表中的所有元素

public static <T> void fill(List<? super T> list, T obj)

5.获取最小值

 public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll)

6.获取最大值

 public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)

7.用新值替换旧值

 public static <T> boolean replaceAll(List<T> list, T oldVal, T newVal)

hutool

CollUtil

1.两个集合的并集

	/**
	 * 两个集合的并集<br>
	 * 针对一个集合中存在多个相同元素的情况,计算两个集合中此元素的个数,保留最多的个数<br>
	 * 例如:集合1:[a, b, c, c, c],集合2:[a, b, c, c]<br>
	 * 结果:[a, b, c, c, c],此结果中只保留了三个c
	 *
	 * @param <T>   集合元素类型
	 * @param coll1 集合1
	 * @param coll2 集合2
	 * @return 并集的集合,返回 {@link ArrayList}
	 */
	public static <T> Collection<T> union(Collection<T> coll1, Collection<T> coll2) {
		final ArrayList<T> list = new ArrayList<>();
		if (isEmpty(coll1)) {
			list.addAll(coll2);
		} else if (isEmpty(coll2)) {
			list.addAll(coll1);
		} else {
			final Map<T, Integer> map1 = countMap(coll1);
			final Map<T, Integer> map2 = countMap(coll2);
			final Set<T> elts = newHashSet(coll2);
			elts.addAll(coll1);
			int m;
			for (T t : elts) {
				m = Math.max(Convert.toInt(map1.get(t), 0), Convert.toInt(map2.get(t), 0));
				for (int i = 0; i < m; i++) {
					list.add(t);
				}
			}
		}
		return list;
	}

2.两个集合的交集

	/**
	 * 两个集合的交集<br>
	 * 针对一个集合中存在多个相同元素的情况,计算两个集合中此元素的个数,保留最少的个数<br>
	 * 例如:集合1:[a, b, c, c, c],集合2:[a, b, c, c]<br>
	 * 结果:[a, b, c, c],此结果中只保留了两个c
	 *
	 * @param <T>   集合元素类型
	 * @param coll1 集合1
	 * @param coll2 集合2
	 * @return 交集的集合,返回 {@link ArrayList}
	 */
	public static <T> Collection<T> intersection(Collection<T> coll1, Collection<T> coll2) {
		final ArrayList<T> list = new ArrayList<>();
		if (isNotEmpty(coll1) && isNotEmpty(coll2)) {
			final Map<T, Integer> map1 = countMap(coll1);
			final Map<T, Integer> map2 = countMap(coll2);
			final Set<T> elts = newHashSet(coll2);
			int m;
			for (T t : elts) {
				m = Math.min(Convert.toInt(map1.get(t), 0), Convert.toInt(map2.get(t), 0));
				for (int i = 0; i < m; i++) {
					list.add(t);
				}
			}
		}
		return list;
	}

3.两个集合的差集

	/**
	 * 两个集合的差集<br>
	 * 针对一个集合中存在多个相同元素的情况,计算两个集合中此元素的个数,保留两个集合中此元素个数差的个数<br>
	 * 例如:集合1:[a, b, c, c, c],集合2:[a, b, c, c]<br>
	 * 结果:[c],此结果中只保留了一个<br>
	 * 任意一个集合为空,返回另一个集合<br>
	 * 两个集合无差集则返回空集合
	 *
	 * @param <T>   集合元素类型
	 * @param coll1 集合1
	 * @param coll2 集合2
	 * @return 差集的集合,返回 {@link ArrayList}
	 */
	public static <T> Collection<T> disjunction(Collection<T> coll1, Collection<T> coll2) {
		if (isEmpty(coll1)) {
			return coll2;
		}
		if (isEmpty(coll2)) {
			return coll1;
		}

		final ArrayList<T> result = new ArrayList<>();
		final Map<T, Integer> map1 = countMap(coll1);
		final Map<T, Integer> map2 = countMap(coll2);
		final Set<T> elts = newHashSet(coll2);
		elts.addAll(coll1);
		int m;
		for (T t : elts) {
			m = Math.abs(Convert.toInt(map1.get(t), 0) - Convert.toInt(map2.get(t), 0));
			for (int i = 0; i < m; i++) {
				result.add(t);
			}
		}
		return result;
	}

4.判断两个集合是否至少有一个共同的元素

	/**
	 * 其中一个集合在另一个集合中是否至少包含一个元素,即是两个集合是否至少有一个共同的元素
	 *
	 * @param coll1 集合1
	 * @param coll2 集合2
	 * @return 其中一个集合在另一个集合中是否至少包含一个元素
	 * @see #intersection
	 * @since 2.1
	 */
	public static boolean containsAny(Collection<?> coll1, Collection<?> coll2) {
		if (isEmpty(coll1) || isEmpty(coll2)) {
			return false;
		}
		if (coll1.size() < coll2.size()) {
			for (Object object : coll1) {
				if (coll2.contains(object)) {
					return true;
				}
			}
		} else {
			for (Object object : coll2) {
				if (coll1.contains(object)) {
					return true;
				}
			}
		}
		return false;
	}

5.判断集合2是否为集合1的子集

	/**
	 * 集合1中是否包含集合2中所有的元素,即集合2是否为集合1的子集
	 *
	 * @param coll1 集合1
	 * @param coll2 集合2
	 * @return 集合1中是否包含集合2中所有的元素
	 * @since 4.5.12
	 */
	public static boolean containsAll(Collection<?> coll1, Collection<?> coll2) {
		if (isEmpty(coll1) || isEmpty(coll2) || coll1.size() < coll2.size()) {
			return false;
		}

		for (Object object : coll2) {
			if (false == coll1.contains(object)) {
				return false;
			}
		}
		return true;
	}

6.根据集合返回一个元素计数的 Map

	/**
	 * 根据集合返回一个元素计数的 {@link Map}<br>
	 * 所谓元素计数就是假如这个集合中某个元素出现了n次,那将这个元素做为key,n做为value<br>
	 * 例如:[a,b,c,c,c] 得到:<br>
	 * a: 1<br>
	 * b: 1<br>
	 * c: 3<br>
	 *
	 * @param <T>        集合元素类型
	 * @param collection 集合
	 * @return {@link Map}
	 * @see IterUtil#countMap(Iterable)
	 */
	public static <T> Map<T, Integer> countMap(Iterable<T> collection) {
		return IterUtil.countMap(collection);
	}

7.以 conjunction 为分隔符将集合转换为字符串

	/**
	 * 以 conjunction 为分隔符将集合转换为字符串<br>
	 * 如果集合元素为数组、{@link Iterable}或{@link Iterator},则递归组合其为字符串
	 *
	 * @param <T>         集合元素类型
	 * @param iterable    {@link Iterable}
	 * @param conjunction 分隔符
	 * @return 连接后的字符串
	 * @see IterUtil#join(Iterable, CharSequence)
	 */
	public static <T> String join(Iterable<T> iterable, CharSequence conjunction) {
		return IterUtil.join(iterable, conjunction);
	}

实例:

    @Test
    public void test() {
        List<List<Integer>> list = CollUtil.newArrayList(Lists.newArrayList(1,2,3),Lists.newArrayList(4,5,6));
        String join = CollUtil.join(list, ",");
        System.out.println("join = " + join);
    }        

结果:

join = 1,2,3,4,5,6

8.截取集合的部分

/**
 * 截取集合的部分
 *
 * @param <T>   集合元素类型
 * @param list  被截取的数组
 * @param start 开始位置(包含)
 * @param end   结束位置(不包含)
 * @param step  步进
 * @return 截取后的数组,当开始位置超过最大时,返回空的List
 * @since 4.0.6
 */
public static <T> List<T> sub(List<T> list, int start, int end, int step) {
   if (list == null) {
      return null;
   }

   if (list.isEmpty()) {
      return new ArrayList<>(0);
   }

   final int size = list.size();
   if (start < 0) {
      start += size;
   }
   if (end < 0) {
      end += size;
   }
   if (start == size) {
      return new ArrayList<>(0);
   }
   if (start > end) {
      int tmp = start;
      start = end;
      end = tmp;
   }
   if (end > size) {
      if (start >= size) {
         return new ArrayList<>(0);
      }
      end = size;
   }

   if (step <= 1) {
      return list.subList(start, end);
   }

   final List<T> result = new ArrayList<>();
   for (int i = start; i < end; i += step) {
      result.add(list.get(i));
   }
   return result;
}

实例:

@Test
public void test1() {
    List<Integer> list = CollUtil.newArrayList(1, 2, 3, 4, 5, 6, 7,8,9,10);
    List<Integer> result = CollUtil.sub(list, 0, 10, 2);
    System.out.println("result = " + result);
}

结果:

result = [1, 3, 5, 7, 9]

9.对集合按照指定长度分段,每一个段为单独的集合,返回这个集合的列表

/**
 * 对集合按照指定长度分段,每一个段为单独的集合,返回这个集合的列表
 *
 * @param <T>        集合元素类型
 * @param collection 集合
 * @param size       每个段的长度
 * @return 分段列表
 */
public static <T> List<List<T>> split(Collection<T> collection, int size) {
   final List<List<T>> result = new ArrayList<>();

   ArrayList<T> subList = new ArrayList<>(size);
   for (T t : collection) {
      if (subList.size() >= size) {
         result.add(subList);
         subList = new ArrayList<>(size);
      }
      subList.add(t);
   }
   result.add(subList);
   return result;
}

实例:

@Test
public void test2() {
    List<Integer> list = CollUtil.newArrayList(1, 2, 3, 4, 5, 6, 7,8,9,10);
    List<List<Integer>> result = CollUtil.split(list, 2);
    System.out.println("result = " + result);
}

结果:

result = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]

10.去除空元素,此方法直接修改原集合

/**
 * 去除{@code null} 元素,此方法直接修改原集合
 *
 * @param <T>        集合类型
 * @param <E>        集合元素类型
 * @param collection 集合
 * @return 处理后的集合
 * @since 3.2.2
 */
public static <T extends Collection<E>, E> T removeNull(T collection) {
   return filter(collection, Objects::nonNull);
}

/**
 * 去除{@code null}或者"" 元素,此方法直接修改原集合
 *
 * @param <T>        集合类型
 * @param <E>        集合元素类型
 * @param collection 集合
 * @return 处理后的集合
 * @since 3.2.2
 */
public static <T extends Collection<E>, E extends CharSequence> T removeEmpty(T collection) {
   return filter(collection, StrUtil::isNotEmpty);
}

/**
 * 去除{@code null}或者""或者空白字符串 元素,此方法直接修改原集合
 *
 * @param <T>        集合类型
 * @param <E>        集合元素类型
 * @param collection 集合
 * @return 处理后的集合
 * @since 3.2.2
 */
public static <T extends Collection<E>, E extends CharSequence> T removeBlank(T collection) {
   return filter(collection, StrUtil::isNotBlank);
}

11.获取给定Bean列表中指定字段名对应字段值的列表

/**
 * 获取给定Bean列表中指定字段名对应字段值的列表<br>
 * 列表元素支持Bean与Map
 *
 * @param collection Bean集合或Map集合
 * @param fieldName  字段名或map的键
 * @return 字段值列表
 * @since 3.1.0
 */
public static List<Object> getFieldValues(Iterable<?> collection, final String fieldName) {
   return getFieldValues(collection, fieldName, false);
}

实例:

@Test
public void test3() {
    List<Map<String, String>> list = new ArrayList<>();
    Map<String, String> map = new HashMap<>();
    map.put("name", "skh");
    map.put("address", "西湖区");
    Map<String, String> map1 = new HashMap<>();
    map1.put("name", "csn");
    map1.put("address", "西湖区");
    list.add(map);
    list.add(map1);
    List<String> result = CollUtil.getFieldValues(list, "name", String.class);
    System.out.println("result = " + result);
}

结果:

result = [skh, csn]

12.映射键值

/**
 * 映射键值(参考Python的zip()函数)<br>
 * 例如:<br>
 * keys = a,b,c,d<br>
 * values = 1,2,3,4<br>
 * delimiter = , 则得到的Map是 {a=1, b=2, c=3, d=4}<br>
 * 如果两个数组长度不同,则只对应最短部分
 *
 * @param keys      键列表
 * @param values    值列表
 * @param delimiter 分隔符
 * @param isOrder   是否有序
 * @return Map
 * @since 3.0.4
 */
public static Map<String, String> zip(String keys, String values, String delimiter, boolean isOrder) {
   return ArrayUtil.zip(StrUtil.split(keys, delimiter), StrUtil.split(values, delimiter), isOrder);
}

13.行转列,合并相同的键,值合并为列表

/**
 * 行转列,合并相同的键,值合并为列表<br>
 * 将Map列表中相同key的值组成列表做为Map的value<br>
 * 是{@link #toMapList(Map)}的逆方法<br>
 * 比如传入数据:
 *
 * <pre>
 * [
 *  {a: 1, b: 1, c: 1}
 *  {a: 2, b: 2}
 *  {a: 3, b: 3}
 *  {a: 4}
 * ]
 * </pre>
 * <p>
 * 结果是:
 *
 * <pre>
 * {
 *   a: [1,2,3,4]
 *   b: [1,2,3,]
 *   c: [1]
 * }
 * </pre>
 *
 * @param <K>     键类型
 * @param <V>     值类型
 * @param mapList Map列表
 * @return Map
 * @see MapUtil#toListMap(Iterable)
 */
public static <K, V> Map<K, List<V>> toListMap(Iterable<? extends Map<K, V>> mapList) {
   return MapUtil.toListMap(mapList);
}

14.列转行。将Map中值列表分别按照其位置与key组成新的map

/**
 * 列转行。将Map中值列表分别按照其位置与key组成新的map。<br>
 * 是{@link #toListMap(Iterable)}的逆方法<br>
 * 比如传入数据:
 *
 * <pre>
 * {
 *   a: [1,2,3,4]
 *   b: [1,2,3,]
 *   c: [1]
 * }
 * </pre>
 * <p>
 * 结果是:
 *
 * <pre>
 * [
 *  {a: 1, b: 1, c: 1}
 *  {a: 2, b: 2}
 *  {a: 3, b: 3}
 *  {a: 4}
 * ]
 * </pre>
 *
 * @param <K>     键类型
 * @param <V>     值类型
 * @param listMap 列表Map
 * @return Map列表
 * @see MapUtil#toMapList(Map)
 */
public static <K, V> List<Map<K, V>> toMapList(Map<K, ? extends Iterable<V>> listMap) {
   return MapUtil.toMapList(listMap);
}

15.根据元素的指定字段名分组,非Bean都放在第一个分组中

/**
 * 根据元素的指定字段名分组,非Bean都放在第一个分组中
 *
 * @param <T>        元素类型
 * @param collection 集合
 * @param fieldName  元素Bean中的字段名,非Bean都放在第一个分组中
 * @return 分组列表
 */
public static <T> List<List<T>> groupByField(Collection<T> collection, final String fieldName) {
   return group(collection, new Hash<T>() {
      private final List<Object> fieldNameList = new ArrayList<>();

      @Override
      public int hash(T t) {
         if (null == t || false == BeanUtil.isBean(t.getClass())) {
            // 非Bean放在同一子分组中
            return 0;
         }
         final Object value = ReflectUtil.getFieldValue(t, fieldName);
         int hash = fieldNameList.indexOf(value);
         if (hash < 0) {
            fieldNameList.add(value);
            return fieldNameList.size() - 1;
         } else {
            return hash;
         }
      }
   });
}

实例:

@Test
public void test4() {
    List<UserDO> list = new ArrayList<>();
    UserDO userDO1 = new UserDO(1, "skh");
    UserDO userDO2 = new UserDO(2, "csn");
    UserDO userDO3 = new UserDO(3 ,"skh");
    list.add(userDO1);
    list.add(userDO2);
    list.add(userDO3);
    List<List<UserDO>> result = CollUtil.groupByField(list, "name");
    System.out.println("result = " + result);
}

结果:

result = [[UserDO(id=1, name=skh), UserDO(id=3, name=skh)], [UserDO(id=2, name=csn)]]

MapUtil

1.将键值对转换为二维数组

/**
 * 将键值对转换为二维数组,第一维是key,第二纬是value
 *
 * @param map map
 * @return 数组
 * @since 4.1.9
 */
public static Object[][] toObjectArray(Map<?, ?> map) {
   if (map == null) {
      return null;
   }
   final Object[][] result = new Object[map.size()][2];
   if (map.isEmpty()) {
      return result;
   }
   int index = 0;
   for (Entry<?, ?> entry : map.entrySet()) {
      result[index][0] = entry.getKey();
      result[index][1] = entry.getValue();
      index++;
   }
   return result;
}

2.过滤

/**
 * 过滤<br>
 * 过滤过程通过传入的Editor实现来返回需要的元素内容,这个Filter实现可以实现以下功能:
 *
 * <pre>
 * 1、过滤出需要的对象,如果返回null表示这个元素对象抛弃
 * </pre>
 *
 * @param <K>    Key类型
 * @param <V>    Value类型
 * @param map    Map
 * @param filter 编辑器接口
 * @return 过滤后的Map
 * @since 3.1.0
 */
public static <K, V> Map<K, V> filter(Map<K, V> map, Filter<Entry<K, V>> filter) {
   if (null == map || null == filter) {
      return map;
   }

   final Map<K, V> map2 = ObjectUtil.clone(map);
   if (isEmpty(map2)) {
      return map2;
   }

   map2.clear();
   for (Entry<K, V> entry : map.entrySet()) {
      if (filter.accept(entry)) {
         map2.put(entry.getKey(), entry.getValue());
      }
   }
   return map2;
}

/**
 * 过滤Map保留指定键值对,如果键不存在跳过
 *
 * @param <K>  Key类型
 * @param <V>  Value类型
 * @param map  原始Map
 * @param keys 键列表
 * @return Map 结果,结果的Map类型与原Map保持一致
 * @since 4.0.10
 */
@SuppressWarnings("unchecked")
public static <K, V> Map<K, V> filter(Map<K, V> map, K... keys) {
   final Map<K, V> map2 = ObjectUtil.clone(map);
   if (isEmpty(map2)) {
      return map2;
   }

   map2.clear();
   for (K key : keys) {
      if (map.containsKey(key)) {
         map2.put(key, map.get(key));
      }
   }
   return map2;
}

3.Map的键和值互换

/**
 * Map的键和值互换
 *
 * @param <T> 键和值类型
 * @param map Map对象,键值类型必须一致
 * @return 互换后的Map
 * @since 3.2.2
 */
public static <T> Map<T, T> reverse(Map<T, T> map) {
   return filter(map, (Editor<Entry<T, T>>) t -> new Entry<T, T>() {

      @Override
      public T getKey() {
         return t.getValue();
      }

      @Override
      public T getValue() {
         return t.getKey();
      }

      @Override
      public T setValue(T value) {
         throw new UnsupportedOperationException("Unsupported setValue method !");
      }
   });
}

4.获取Map指定key的值,并转换为指定类型

/**
 * 获取Map指定key的值,并转换为指定类型
 *
 * @param <T>  目标值类型
 * @param map  Map
 * @param key  键
 * @param type 值类型
 * @return 值
 * @since 4.0.6
 */
public static <T> T get(Map<?, ?> map, Object key, Class<T> type) {
   return null == map ? null : Convert.convert(type, map.get(key));
}

5.重命名键

/**
 * 重命名键<br>
 * 实现方式为一处然后重新put,当旧的key不存在直接返回<br>
 * 当新的key存在,抛出{@link IllegalArgumentException} 异常
 *
 * @param <K>    key的类型
 * @param <V>    value的类型
 * @param map    Map
 * @param oldKey 原键
 * @param newKey 新键
 * @return map
 * @throws IllegalArgumentException 新key存在抛出此异常
 * @since 4.5.16
 */
public static <K, V> Map<K, V> renameKey(Map<K, V> map, K oldKey, K newKey) {
   if (isNotEmpty(map) && map.containsKey(oldKey)) {
      if (map.containsKey(newKey)) {
         throw new IllegalArgumentException(StrUtil.format("The key '{}' exist !", newKey));
      }
      map.put(newKey, map.remove(oldKey));
   }
   return map;
}

Guava

Multimap->Map<String,List>

@Test
public void test6() {
    //Multimap multimap = ArrayListMultimap.create(); //arraylist
    Multimap multimap = HashMultimap.create(); //hashmap
    multimap.put("name", "skh");
    multimap.put("name", "csn");
    multimap.put("name", "Bob");
    multimap.put("age", 1);
    multimap.put("age", 2);
    multimap.put("age", 3);
    System.out.println("result = " + multimap);
}

结果:

result = {name=[Bob, skh, csn], age=[1, 2, 3]}

Multiset:一个名叫set的计数器

Multiset的作用就是对重复元素计数…

内部实现使用HashMap来保存key->count的一个映射关系.

@Test
public void test7() {
    Multiset<String> s = HashMultiset.create();
    s.add("1");
    s.add("1");
    s.add("2");
    s.add("2");
    s.add("3");
    //获取set里的元素(无重复)
    Set<String> strings = s.elementSet();
    System.out.println("strings = " + strings);
    //统计元素出现的次数
    int i = s.count("1");
    System.out.println("i = " + i);
}

结果:

strings = [1, 2, 3]
i = 2

BiMap -> value也不可以重复的双向Map

它必须保证key和value都没有重复值.因为他支持根据value获取key,即将HashMap的key和value进行调换.

这个类适合用在key和value都唯一,且经常会出现根据value来获取key的情况.

@Test
public void test8() {
    BiMap<String, String> m = HashBiMap.create();
    m.put("skh", "111");
    //通过key获取value
    String value = m.get("skh");
    System.out.println("value = " + value);
    //通过value获取key
    String key = m.inverse().get("111");
    System.out.println("key = " + key);
}

结果:

value = 111
key = skh

Table -> Map<String,Map<String,Object>> 多个索引映射一个结果

    @Test
    public void test9() {
       //多个索引对应一个结果,比如这里的rowKey和columnKey都能查找到指定的value
        Table<String,String,Integer> table = HashBasedTable.create();
        table.put("张三","语文",93);
        table.put("张三","数学",100);
        table.put("张三","英语",99);

        table.put("李四","语文",98);
        table.put("李四","数学",90);
        table.put("李四","英语",89);
        System.out.println(table.row("李四"));       // {语文=98, 数学=90, 英语=89}
        System.out.println(table.get("张三","英语")); // 99
        System.out.println(table.get("张三","体育")); // null
        Map<String, Integer> columnMap = table.column("语文"); //{张三=93, 李四=98}
    }

ComparisonChain -> 功能强大且好看的多字段比较方法

在面对多个字段排序比较的场景,一般我们的代码都会比较难看,比如对下面这个类:

private static class Student {
    int id;
    String name;
    int age;
}

首先比较id,id相等比较name,name相等比较age,这是一种很常见的多字段比较策略.那么我们给Student类加上Comparable的实现.

// 为了简洁起见,没有写外部类代码,只贴了重写的comparTo方法.
    @Override
    public int compareTo(Object o) {
        Student s = (Student) o;
        int idResult = s.id - this.id;
        int nameResult = s.name.compareTo(this.name);
        int ageResult = s.age - this.age;

        return idResult != 0 ? idResult : nameResult != 0 ? nameResult : ageResult;
    }

最后那一串?:?:是不是看的眼睛疼,当然你可以选择三重if-else,我觉得也没好到哪里去.

但是可以使用ComparisonChain,这名字一看就是比较链,非常适合我们的场景.改写如下:

 @Override
        public int compareTo(Object o) {
            Student s = (Student) o;
            return ComparisonChain.start().compare(s.id, this.id).compare(s.name, this.name).compare(s.age, this.age).
                    result();
        }

找出2个Map的不同之处,以Map形式返回

    @Test
    public void test10() {
        HashMap<String, String> left = new HashMap<>();
        left.put("name", "skh");
        left.put("addr", "西湖区");
        left.put("age", "25");
        left.put("sex", "男");

        HashMap<String, String> right = new HashMap<>();
        right.put("name", "csn");
        right.put("addr", "西湖区");
        right.put("age", "24");
        right.put("birth", "1993");

        MapDifference<String, String> difference = Maps.difference(left, right);
        Map<String, String> leftMap = difference.entriesOnlyOnLeft();
        System.out.println("leftMap = " + leftMap);

        Map<String, String> rightMap = difference.entriesOnlyOnRight();
        System.out.println("rightMap = " + rightMap);

        Map<String, MapDifference.ValueDifference<String>> differenceMap = difference.entriesDiffering();
        System.out.println("differenceMap = " + differenceMap);

        Map<String, String> commonMap = difference.entriesInCommon();
        System.out.println("commonMap = " + commonMap);

    }

结果:

leftMap = {sex=男}
rightMap = {birth=1993}
differenceMap = {name=(skh, csn), age=(25, 24)}
commonMap = {addr=西湖区}

求笛卡尔积

    @Test
    public void test11() {
        Set<Integer> set1 = Sets.newHashSet(1, 2, 3);
        Set<Integer> set2 = Sets.newHashSet(4,5,6);
        //Set<Integer> set3 = Sets.newHashSet(7,8,9);
        Set<List<Integer>> result = Sets.cartesianProduct(set1, set2);
        System.out.println("result = " + result);
    }

结果:

result = [[1, 4], [1, 5], [1, 6], [2, 4], [2, 5], [2, 6], [3, 4], [3, 5], [3, 6]]

求集合的所有子集,按指定长度分割

    @Test
    public void test12() {
        Set<Integer> set1 = Sets.newHashSet(1, 2, 3);
        Set<Set<Integer>> result = Sets.combinations(set1, 2);
        for (Set<Integer> set : result) {
            System.out.println("set = " + set);
        }
        System.out.println("result = " + result);
    }
    
    

结果:

set = [1, 2]
set = [1, 3]
set = [2, 3]
result = Sets.combinations([1, 2, 3], 2)

求集合的所有子集

    @Test
    public void test13() {
        Set<Integer> set1 = Sets.newHashSet(1, 2, 3);

        Set<Set<Integer>> result = Sets.powerSet(set1);
        for (Set<Integer> set : result) {
            System.out.println("set = " + set);
        }

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

结果:

set = []
set = [1]
set = [2]
set = [1, 2]
set = [3]
set = [1, 3]
set = [2, 3]
set = [1, 2, 3]
result = powerSet({1=0, 2=1, 3=2})

求差集

    @Test
    public void test14() {
        Set<Integer> set1 = Sets.newHashSet(1, 2, 3,5,6);
        Set<Integer> set2 = Sets.newHashSet(1, 2, 4);

        Sets.SetView<Integer> result = Sets.difference(set1, set2); //返回set1中不存在的数据,会忽略set2中的元素
        result.forEach(i -> System.out.println("i = " + i));
        System.out.println("result = " + result);
    }

结果:

i = 3
i = 5
i = 6
result = [3, 5, 6]

求交集

@Test
public void test15() {
    Set<Integer> set1 = Sets.newHashSet(1, 2, 3,5,6);
    Set<Integer> set2 = Sets.newHashSet(1, 2, 4);

    //交集
    Sets.SetView<Integer> result = Sets.intersection(set1, set2);
    result.forEach(i -> System.out.println("i = " + i));
    System.out.println("result = " + result);
}

结果:

i = 1
i = 2
result = [1, 2]

求并集

    @Test
    public void test16() {
        Set<Integer> set1 = Sets.newHashSet(1, 2, 3,5,6);
        Set<Integer> set2 = Sets.newHashSet(1, 2, 4);

        //求并集
        Sets.SetView<Integer> result = Sets.union(set1, set2);
        result.forEach(i -> System.out.println("i = " + i));
        System.out.println("result = " + result);
    }

结果:

i = 1
i = 2
i = 3
i = 5
i = 6
i = 4
result = [1, 2, 3, 5, 6, 4]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值