package com.github.looly.hutool;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.Stack;
/**
* 集合相关工具类,包括数组
*
* @author xiaoleilu
*
*/
public class CollectionUtil {
/**
* 以 conjunction 为分隔符将集合转换为字符串
*
* @param <T> 被处理的集合
* @param collection 集合
* @param conjunction 分隔符
* @return 连接后的字符串
*/
public static <T> String join(Iterable<T> collection, String conjunction) {
StringBuilder sb = new StringBuilder();
boolean isFirst = true;
for (T item : collection) {
if (isFirst) {
isFirst = false;
} else {
sb.append(conjunction);
}
sb.append(item);
}
return sb.toString();
}
/**
* 以 conjunction 为分隔符将数组转换为字符串
*
* @param <T> 被处理的集合
* @param array 数组
* @param conjunction 分隔符
* @return 连接后的字符串
*/
public static <T> String join(T[] array, String conjunction) {
StringBuilder sb = new StringBuilder();
boolean isFirst = true;
for (T item : array) {
if (isFirst) {
isFirst = false;
} else {
sb.append(conjunction);
}
sb.append(item);
}
return sb.toString();
}
/**
* 将多个集合排序并显示不同的段落(分页)
* @param pageNo 页码
* @param numPerPage 每页的条目数
* @param comparator 比较器
* @param colls 集合数组
* @return 分页后的段落内容
*/
@SafeVarargs
public static <T> List<T> sortPageAll(int pageNo, int numPerPage, Comparator<T> comparator, Collection<T>... colls) {
final List<T> result = new ArrayList<T>();
for (Collection<T> coll : colls) {
result.addAll(coll);
}
Collections.sort(result, comparator);
//第一页且数目少于第一页显示的数目
if(pageNo <=1 && result.size() <= numPerPage) {
return result;
}
final int[] startEnd = PageUtil.transToStartEnd(pageNo, numPerPage);
return result.subList(startEnd[0], startEnd[1]);
}
/**
* 将多个集合排序并显示不同的段落(分页)
* @param pageNo 页码
* @param numPerPage 每页的条目数
* @param comparator 比较器
* @param colls 集合数组
* @return 分业后的段落内容
*/
@SafeVarargs
public static <T> List<T> sortPageAll2(int pageNo, int numPerPage, Comparator<T> comparator, Collection<T>... colls) {
BoundedPriorityQueue<T> queue = new BoundedPriorityQueue<T>(pageNo * numPerPage);
for (Collection<T> coll : colls) {
queue.addAll(coll);
}
//第一页且数目少于第一页显示的数目
if(pageNo <=1 && queue.size() <= numPerPage) {
return queue.toList();
}
final int[] startEnd = PageUtil.transToStartEnd(pageNo, numPerPage);
return queue.toList().subList(startEnd[0], startEnd[1]);
}
/**
* 将Set排序(根据Entry的值)
*
* @param set 被排序的Set
* @return 排序后的Set
*/
public static List<Entry<Long, Long>> sortEntrySetToList(Set<Entry<Long, Long>> set) {
List<Entry<Long, Long>> list = new LinkedList<Map.Entry<Long, Long>>(set);
Collections.sort(list, new Comparator<Entry<Long, Long>>(){
@Override
public int compare(Entry<Long, Long> o1, Entry<Long, Long> o2) {
if (o1.getValue() > o2.getValue()) return 1;
if (o1.getValue() < o2.getValue()) return -1;
return 0;
}
});
return list;
}
/**
* 切取部分数据
*
* @param <T> 集合元素类型
* @param surplusAlaDatas 原数据
* @param partSize 每部分数据的长度
* @return 切取出的数据或null
*/
public static <T> List<T> popPart(Stack<T> surplusAlaDatas, int partSize) {
if (surplusAlaDatas == null || surplusAlaDatas.size() <= 0) return null;
List<T> currentAlaDatas = new ArrayList<T>();
int size = surplusAlaDatas.size();
// 切割
if (size > partSize) {
for (int i = 0; i < partSize; i++) {
currentAlaDatas.add(surplusAlaDatas.pop());
}
} else {
for (int i = 0; i < size; i++) {
currentAlaDatas.add(surplusAlaDatas.pop());
}
}
return currentAlaDatas;
}
/**
* 新建一个HashMap
*
* @return HashMap对象
*/
public static <T, K> HashMap<T, K> newHashMap() {
return new HashMap<T, K>();
}
/**
* 新建一个HashMap
* @param size 初始大小,由于默认负载因子0.75,传入的size会实际初始大小为size / 0.75
* @return HashMap对象
*/
public static <T, K> HashMap<T, K> newHashMap(int size) {
return new HashMap<T, K>((int)(size / 0.75));
}
/**
* 新建一个HashSet
*
* @return HashSet对象
*/
public static <T> HashSet<T> newHashSet() {
return new HashSet<T>();
}
/**
* 新建一个HashSet
*
* @return HashSet对象
*/
@SafeVarargs
public static <T> HashSet<T> newHashSet(T... ts) {
HashSet<T> set = new HashSet<T>();
for (T t : ts) {
set.add(t);
}
return set;
}
/**
* 新建一个ArrayList
*
* @return ArrayList对象
*/
public static <T> ArrayList<T> newArrayList() {
return new ArrayList<T>();
}
/**
* 新建一个ArrayList
*
* @return ArrayList对象
*/
@SafeVarargs
public static <T> ArrayList<T> newArrayList(T... values) {
ArrayList<T> list = new ArrayList<T>(values.length);
for (T t : values) {
list.add(t);
}
return list;
}
/**
* 将新元素添加到已有数组中<br/>
* 添加新元素会生成一个新的数组,不影响原数组
*
* @param buffer 已有数组
* @param newElement 新元素
* @return 新数组
*/
public static <T> T[] append(T[] buffer, T newElement) {
T[] t = resize(buffer, buffer.length + 1, newElement.getClass());
t[buffer.length] = newElement;
return t;
}
/**
* 生成一个新的重新设置大小的数组
*
* @param buffer 原数组
* @param newSize 新的数组大小
* @param componentType 数组元素类型
* @return 调整后的新数组
*/
public static <T> T[] resize(T[] buffer, int newSize, Class<?> componentType) {
T[] newArray = newArray(componentType, newSize);
System.arraycopy(buffer, 0, newArray, 0, buffer.length >= newSize ? newSize : buffer.length);
return newArray;
}
/**
* 新建一个空数组
* @param componentType 元素类型
* @param newSize 大小
* @return 空数组
*/
@SuppressWarnings("unchecked")
public static <T> T[] newArray(Class<?> componentType, int newSize) {
return (T[]) Array.newInstance(componentType, newSize);
}
/**
* 生成一个新的重新设置大小的数组<br/>
* 新数组的类型为原数组的类型
*
* @param buffer 原数组
* @param newSize 新的数组大小
* @return 调整后的新数组
*/
public static <T> T[] resize(T[] buffer, int newSize) {
return resize(buffer, newSize, buffer.getClass().getComponentType());
}
/**
* 将多个数组合并在一起<br>
* 忽略null的数组
*
* @param arrays 数组集合
* @return 合并后的数组
*/
@SafeVarargs
public static <T> T[] addAll(T[]... arrays) {
if (arrays.length == 1) {
return arrays[0];
}
int length = 0;
for (T[] array : arrays) {
if(array == null) {
continue;
}
length += array.length;
}
T[] result = newArray(arrays.getClass().getComponentType().getComponentType(), length);
length = 0;
for (T[] array : arrays) {
if(array == null) {
continue;
}
System.arraycopy(array, 0, result, length, array.length);
length += array.length;
}
return result;
}
/**
* 克隆数组
* @param array 被克隆的数组
* @return 新数组
*/
public static <T> T[] clone(T[] array) {
if (array == null) {
return null;
}
return array.clone();
}
/**
* 生成一个数字列表<br>
* 自动判定正序反序
* @param excludedEnd 结束的数字(不包含)
* @return 数字列表
*/
public static int[] range(int excludedEnd) {
return range(0, excludedEnd, 1);
}
/**
* 生成一个数字列表<br>
* 自动判定正序反序
* @param includedStart 开始的数字(包含)
* @param excludedEnd 结束的数字(不包含)
* @return 数字列表
*/
public static int[] range(int includedStart, int excludedEnd) {
return range(includedStart, excludedEnd, 1);
}
/**
* 生成一个数字列表<br>
* 自动判定正序反序
* @param includedStart 开始的数字(包含)
* @param excludedEnd 结束的数字(不包含)
* @param step 步进
* @return 数字列表
*/
public static int[] range(int includedStart, int excludedEnd, int step) {
if(includedStart > excludedEnd) {
int tmp = includedStart;
includedStart = excludedEnd;
excludedEnd = tmp;
}
if(step <=0) {
step = 1;
}
int deviation = excludedEnd - includedStart;
int length = deviation / step;
if(deviation % step != 0) {
length += 1;
}
int[] range = new int[length];
for(int i = 0; i < length; i++) {
range[i] = includedStart;
includedStart += step;
}
return range;
}
/**
* 截取数组的部分
* @param list 被截取的数组
* @param start 开始位置(包含)
* @param end 结束位置(不包含)
* @return 截取后的数组,当开始位置超过最大时,返回null
*/
public static <T> List<T> sub(List<T> list, int start, int end) {
if(list == null || list.isEmpty()) {
return null;
}
if(start < 0) {
start = 0;
}
if(end < 0) {
end = 0;
}
if(start > end) {
int tmp = start;
start = end;
end = tmp;
}
final int size = list.size();
if(end > size) {
if(start >= size) {
return null;
}
end = size;
}
return list.subList(start, end);
}
/**
* 截取集合的部分
* @param list 被截取的数组
* @param start 开始位置(包含)
* @param end 结束位置(不包含)
* @return 截取后的数组,当开始位置超过最大时,返回null
*/
public static <T> List<T> sub(Collection<T> list, int start, int end) {
if(list == null || list.isEmpty()) {
return null;
}
return sub(new ArrayList<T>(list), start, end);
}
/**
* 数组是否为空
* @param array 数组
* @return 是否为空
*/
public static <T> boolean isEmpty(T[] array) {
return array == null || array.length == 0;
}
/**
* 数组是否为非空
* @param array 数组
* @return 是否为非空
*/
public static <T> boolean isNotEmpty(T[] array) {
return false == isEmpty(array);
}
/**
* 集合是否为空
* @param collection 集合
* @return 是否为空
*/
public static <T> boolean isEmpty(Collection<T> collection) {
return collection == null || collection.isEmpty();
}
/**
* 集合是否为非空
* @param collection 集合
* @return 是否为非空
*/
public static <T> boolean isNotEmpty(Collection<T> collection) {
return false == isEmpty(collection);
}
/**
* 映射键值(参考Python的zip()函数)<br>
* 例如:<br>
* keys = [a,b,c,d]<br>
* values = [1,2,3,4]<br>
* 则得到的Map是 {a=1, b=2, c=3, d=4}<br>
* 如果两个数组长度不同,则只对应最短部分
* @param keys 键列表
* @param values 值列表
* @return Map
*/
public static <T, K> Map<T, K> zip(T[] keys, K[] values) {
if(isEmpty(keys) || isEmpty(values)) {
return null;
}
final int size = Math.min(keys.length, values.length);
final Map<T, K> map = new HashMap<T, K>((int)(size / 0.75));
for(int i = 0; i < size; i++) {
map.put(keys[i], values[i]);
}
return map;
}
/**
* 映射键值(参考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 值列表
* @return Map
*/
public static Map<String, String> zip(String keys, String values, String delimiter) {
return zip(StrUtil.split(keys, delimiter), StrUtil.split(values, delimiter));
}
/**
* 映射键值(参考Python的zip()函数)<br>
* 例如:<br>
* keys = [a,b,c,d]<br>
* values = [1,2,3,4]<br>
* 则得到的Map是 {a=1, b=2, c=3, d=4}<br>
* 如果两个数组长度不同,则只对应最短部分
* @param keys 键列表
* @param values 值列表
* @return Map
*/
public static <T, K> Map<T, K> zip(Collection<T> keys, Collection<K> values) {
if(isEmpty(keys) || isEmpty(values)) {
return null;
}
final List<T> keyList = new ArrayList<T>(keys);
final List<K> valueList = new ArrayList<K>(values);
final int size = Math.min(keys.size(), values.size());
final Map<T, K> map = new HashMap<T, K>((int)(size / 0.75));
for(int i = 0; i < size; i++) {
map.put(keyList.get(i), valueList.get(i));
}
return map;
}
/**
* 数组中是否包含元素
* @param array 数组
* @param value 被检查的元素
* @return 是否包含
*/
public static <T> boolean contains(T[] array, T value) {
final Class<?> componetType = array.getClass().getComponentType();
boolean isPrimitive = false;
if(null != componetType) {
isPrimitive = componetType.isPrimitive();
}
for (T t : array) {
if(t == value) {
return true;
}else if(false == isPrimitive && null != value && value.equals(t)) {
return true;
}
}
return false;
}
/**
* 将Entry集合转换为HashMap
* @param entryCollection entry集合
* @return Map
*/
public static <T, K> HashMap<T, K> toMap(Collection<Entry<T, K>> entryCollection) {
HashMap<T,K> map = new HashMap<T, K>();
for (Entry<T, K> entry : entryCollection) {
map.put(entry.getKey(), entry.getValue());
}
return map;
}
}