Jeffrey的博客 Jeffrey的博客

左脑编程,右脑写诗

目录
改善Java程序的N个建议(四)
/    

改善Java程序的N个建议(四)

建议66:asList方法产生的List对象不可变更

Arrays.asList方法输入的是一个泛型边长参数,返回一个固定长度的列表,那么来看看下面这个故事:

public class Proposal_66 {
	public static void main(String[] args) {
		// 一周工作五天
		Week[] workDays = {Week.Mon, Week.Tue, Week.Wed, Week.Thu, Week.Fri};
		// 转换为列表
		List<Week> list = Arrays.asList(workDays);
		// 老板让你周六加班,周六变为工作日
		list.add(Week.Sat);
	}
}

enum Week {
	Sun, Mon, Tue, Wed, Thu, Fri, Sat
}

好好的一周五天,周六非得加班?编译通过了,运行呢?

image.png

UnsupportedOperationException,不支持的操作?怎么会不支持list.add(),asList是创建一个new ArrayList对象的,难道ArrayList不支持add方法吗?不应该呀。问题就出在这个ArrayList中,这个ArrayList非java.uril.ArrayList,而是Arrays工具类的一个内置类。

找到这个ArrayList的父类AbstractList,看到他并没有实现add方法,add方法需要其子类去覆写实现,而Aarrays并没有去覆写该方法,这才导致了会有异常抛出。

public void add(int index, E element) {
        throw new UnsupportedOperationException();
}

建议76:集合运算时使用更优雅的方式

在代数运算中我们经常会使用并集、交集、差集,那么在Java中是如何实现的呢?

  1. 并集:也称为合集,使用非常简单,代码如下:
public class Proposal_76 {
	public static void main(String[] args) {
		List<String> list1 = new ArrayList<String>();
		list1.add("A");
		list1.add("B");

		List<String> list2 = new ArrayList<String>();
		list2.add("C");
		list2.add("B");

		// 并集
		list1.addAll(list2);
		System.out.println(list1);
	}
}
  1. 交集:计算交集即计算两个集合共有的元素:
list1.retainAll(list2);
  1. 差集:由所有属于A但不属于B的元素组成的集合,叫做A与B的集
list1.removeAll(list2);
  1. 无重复并集:并集适合A加上集合B,无重复并集则需要确保并集的结果只有一份交集
list2.removeAll(list1);
list1.addAll(list2);

前面几个结果就不一一展示了,展示下无重复并集的结果:
image.png

建议80:由点及面,一叶知秋——集合大家族

Java里有丰富的集合,有重用的ArrayList、HashMap,也有不常用的Stack、Queue,有线程安全的Vector、HashTable,也有线程不安全的LinkedList、TreeMap,有阻塞式的ArrayBlockQueue,也有非阻塞式的PriorityQueue等,具体可以划分为下面几类:

1.List
实现List的接口的集合有:ArrayList、LInkedList、Vector、Stack,其中ArrayList是一个动态数组,LinkedList是一个双向链表,Vector是一个线程安全的动态数组,Stack是一个对象栈,遵循先进后出原则。

2.Set
Set是不包含重复元素的集合,主要实现类有:EnumSet、HashSet、其中EnumSet是枚举类型专用Set,所有元素都是枚举类型,HashSet是以哈希吗决定其元素位置的Set,其原理和HashMap相似,它提供快速插入和查找的方法;TreeSet是一个自动排序的Set,它实现了SortedSet接口。

3.Map
Map类分为排序Map和非排序Map,排序Map主要是TreeMap类,它根据Key值进行自动排序,非排序Map主要包括:HashMap、HashTable、Properties、EnumMap等,其中Properties是HashTable的子类,主要用途是Property文件中加载数据,并提供方便的读写操作;EnumMap则是要求其Key必须是某一个枚举类型。

4.Queue
队列分为两类,一类是阻塞队列,主要有:ArrayBlockQueue、PriorityBlockingQueue、LinkedBlockQueue;另一类是非阻塞队列,无边界、只要内存允许,都可以持续追加元素,最长使用的是PriorityQueue;还有一种队列是双端队列,主要实现类有:ArrayDeque、LinkedBlockingDeque、LinkedList。

5.数组
数组和集合最大的区别是数组能容纳基本类型,而集合不行,且集合底层都是数组。

6.工具类
数组的工具类是java.util.Arrays和java.lang.reflect.Array,集合的工具类是java.util.Collections有了这两个工具类,操作数组和集合会易如反掌,得心应手。

7.扩展类
集合类当然可以自行扩展,想写一个自己的List最好的办法是“拿来主义”,可以使用Apache的commons-collections扩展包,也可以使用Google的google-collections扩展包,这些足以应对我们的开发需求。


标题:改善Java程序的N个建议(四)
作者:Jeffrey