常用工具類的集合方法總結

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章