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

Updated on in Java with 681 views

建议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

Responses
取消