Collections工具类介绍
此类完全由在 collection 上进行操作或返回 collection 的静态方法组成
如果为此类的方法所提供的collection 或类对象为 null,则这些方法都将抛出NullPointerException。
public的可用字段摘要(都用对应的get方法供访问)
public static final List EMPTY_LIST:空的列表(不可变的) public static final Map EMPTY_MAP:空的映射(不可变的) public static final Set EMPTY_SET:空的 set(不可变的)
排序
集合排序,不可为使用不多,啥都不说,直接上例子,解释都放在例子里面
public static void main(String[] args) { List<Integer> list = new ArrayList<>(); list.add(12); list.add(-15); list.add(7); list.add(4); list.add(35); list.add(9); System.out.println("源列表:" + list); //[12, -15, 7, 4, 35, 9] // 排序(自然顺序) Collections.sort(list); System.out.println("自然序:" + list); //[-15, 4, 7, 9, 12, 35] // 逆序 Collections.reverse(list); System.out.println("逆序:" + list); //[35, 12, 9, 7, 4, -15] // 随机排序(扑克牌洗牌经常使用) 每次结果都不一样 Collections.shuffle(list); System.out.println("随机序:" + list); //[9, 4, -15, 12, 7, 35] // 定制排序的用法(根据指定比较器产生的顺序对指定列表进行排序),将int类型转成string进行比较(注意,不再是数字了,排序有变化) Collections.sort(list, Comparator.comparing(String::valueOf)); System.out.println("定制序:" + list); //[-15, 12, 35, 4, 7, 9] // 旋转(旋转效果有点意思) Collections.rotate(list, 3); //[4, 7, 9, -15, 12, 35] System.out.println("旋转3:" + list); Collections.rotate(list, -3); System.out.println("旋转-3:" + list); //[-15, 12, 35, 4, 7, 9] }
对比下结果:
swap 交换两个位置的值
//list-- 在该列表中的调剂元素。 //i-- 要交换的一个元素的索引。 //j-- 要交换的其它元素的索引。 // 请注意i/j都不要超出范围 public static void swap(List<?> list,int i,int j);
案例:
public static void main(String[] args) { List<Integer> list = new ArrayList<>(); list.add(12); list.add(-15); list.add(7); list.add(4); list.add(35); list.add(9); System.out.println("swap之前:" + list); Collections.swap(list, 0, 2); //把0位置元素和2位置交换(备注:若是不可变集合,此处是会抛错的) System.out.println("swap之后:" + list); }
查找及替换操作
public static void main(String[] args) { List<Integer> list = new ArrayList<>(); list.add(12); list.add(-15); list.add(7); list.add(4); list.add(35); list.add(9); System.out.println("源列表:" + list); // 最大值 System.out.println("最大值:" + Collections.max(list)); //35 // 最小值 System.out.println("最小值:" + Collections.min(list)); //-15 // 替换 把所有的-15替换成12 Collections.replaceAll(list, -15, 12); System.out.println("-15替换12:" + list); //[12, 12, 7, 4, 35, 9] // 出现次数(这个特别有用 某个元素出现的此处) 支持找null出现的次数哦~~~~ System.out.println("12出现次数:" + Collections.frequency(list, 12)); //2 // 排序 因为二分查找必须有序 否则可能不准 Collections.sort(list); System.out.println("排序后:" + list); //[4, 7, 9, 12, 12, 35] // 二分查找 (注意,返回的是查找对象的索引,List必须是有序的) System.out.println("-15下标:" + Collections.binarySearch(list, -15)); //-1 没找到就是-1 System.out.println("7下标:" + Collections.binarySearch(list, 7)); //1 System.out.println("35下标:" + Collections.binarySearch(list, 35)); //5 //indexOfSubList:返回指定源列表中第一次出现指定目标列表的起始位置;如果没有出现这样的列表,则返回-1。 //lastIndexOfSubList:同上 (最后一次) 若出现多次的请,会有差异 System.out.println(Collections.indexOfSubList(list, Arrays.asList(7, 9))); //1 System.out.println(Collections.lastIndexOfSubList(list, Arrays.asList(7, 9))); //1 //fill:用后面元素,把所有元素都给替换掉 Collections.fill(list, 1); System.out.println("fill后的:" + list); //[1, 1, 1, 1, 1, 1] }
同步和只读
这个使用起来比较简单,但是能提高效率和安全性。特别是只读的,建议大家多使用
SynchronizedList(), SynchronizedSet(),unmodifiableCollection等等
singletonXXX
public static <T> Set<T> singleton(T o) { return new SingletonSet<>(o); } public static <T> List<T> singletonList(T o) { return new SingletonList<>(o); } public static <K,V> Map<K,V> singletonMap(K key, V value) { return new SingletonMap<>(key, value); }
以前我们要初始化一个元素,到List,我们经常这么用:Arrays.asList(),那么今后,若只有一个元素需要构建list,请使用singletonXXX吧~~~
singletonXXX优势分析:
这个方法主要用于只有一个元素的优化,减少内存分配,无需分配额外的内存,可以从SingletonList内部类看得出来,由于只有一个element,因此可以做到内存分配最小化,相比之下ArrayList的DEFAULT_CAPACITY=10个
同样需要注意的是:他们返回都是只读的List,如果调用修改接口,将会抛出UnsupportedOperationException
其它
addAll(Collection<? super T> c, T… elements):将所有指定元素添加到指定collection 中
copy(List<? super T> dest, List<? extends T> src):将所有元素从一个列表复制到另一个列表(挺好用)
disjoint(Collection<?> c1, Collection<?> c2):如果两个指定collection 中没有相同的元素,则返回 true (判断两个集合是否有重合的元素) 建议使用,毕竟JDK的算法还不错
nCopies(int n, T o):返回由指定对象的n 个副本组成的不可变列表 (可以copy)
public static void main(String[] args) { //若需要生成相同元素,可用这个快速生成 List<Integer> list = Collections.nCopies(5, new Integer(1)); System.out.println(list); //[1, 1, 1, 1, 1] //注意,这里返回true,所以需要注意:长度虽然是5 但是都是副本的拷贝,变一个其余都变的 System.out.println(list.size()); System.out.println(list.get(0) == list.get(1)); //true }
asLifoQueue(Deque deque):以后进先出(Lifo) Queue 的形式返回某个 Deque 的视图
Deque是接口,具体继承关系为:Collection–>Queue–>Deque–>LinkedList、ArrayDeque、LinkedBlockingDeque
**Queue(队列)接口与List、Set同一级别,都是继承了Collection接口。Queue使用时要尽量避免Collection的add()和remove()方法,而是要使用offer()来加入元素,使用poll()来获取并移出元素。**它们的优点是通过返回值可以判断成功与否,add()和remove()方法在失败的时候会抛出异常。 如果要使用前端而不移出该元素,使用element()或者peek()方法。
Deque(双端队列)接口支持两端插入和移除元素。名称deque 是“double ended queue(双端队列)”的缩写,通常读为“deck”。
public static void main(String[] args) { //LinkedList 是先进先出的First-in-first-out fifo LinkedList<Integer> llist1 = new LinkedList<>(Arrays.asList(2, 4, 6)); System.out.println(llist1); //[2, 4, 6] //offer方法底层调用add方法,一模一样的 System.out.println(llist1.add(5)); //true 添加成功返回的true System.out.println(llist1); //[2, 4, 6, 5] 发现添加到尾部的 //element和peek都是把队列首部元素取出 但是不移除 poll()方法也是取出,但是会移除 System.out.println(llist1.element()); //2 System.out.println(llist1.peek()); //2 System.out.println(llist1); //[2, 4, 6, 5, 9] System.out.println("-------------------------"); //变成Last-in-first-out lifo的队列 也就是后进先出(上面LinkedList是先进先出,需要注意) Queue q = Collections.asLifoQueue(llist1); System.out.println(q); System.out.println(q.add(5)); //true System.out.println(q); //[5, 2, 4, 6, 5] }
- checkedCollection、checkedList等等:返回类型检查的集合,更安全了。(备注:现在都使用泛型集合了,不太建议使用了。当然MyBatis里存在一些问题,可以考虑使用)
public static void main(String[] args) { //这样子,下面程序不抱错,显然是纯在安全隐患的 //List<String> list = Arrays.asList("12","23"); //List obj = list; list中存在了一个非String类型,程序执行到这里不会报错 //obj.add(112); List<String> list = Arrays.asList("12", "23"); List<String> safeList = Collections.checkedList(list, String.class); List obj = safeList; //检查容器视图受限于虚拟机可运行的运行时检查 这里就报错了 obj.add(new Date());//只有执行到这一步才会抛出java.lang.ClassCastException }
总结
Arryas
和Collections
是JDK提供给我们的非常好用的两个工具类。工欲善其事必先利其器,掌握了更多的好用工具,我们才能事半功倍