一、摘要
本博文主要介绍JAVA容器(集合)的一些基础知识及功能特性,目的是对JAVA容器有一个宏观的了解。Java集合类是一种特别有用的工具类,可用于存储数量不等的对象,可以实现常用的数据结构,如栈、队列等。保存具有映射关系的关联数组(Map)。Java集合(Collection)大致为分Set、List、Queue和Map四种体系。其中Set代表无序不可重复的集合,List代表有序、可重复的集合,etc...
二、Java集合概述
集合和数组不太一样,数组可以存储基本类型的值,也可以存储对象(实际上保存的是对象的引用),而集合只负责存储对象。Java集合类主要由两个接口派生出来:Collection与Map。
1.Set集合
Set集合类似一个“大罐子”,我们可以将多个对象直接“丢进”Set集合里,Set集合不会记住元素的添加顺序,但是添加的元素是不可重复的,实际上大家也可以想到,Set其实就是Collection,只是行为略有不同而已。主要包含三个子类:HashSet(用的最多)、TreeSet以及LinkedHashSet。
1)HashSet
HashSet是Set典型实现,使用最多的一个类,其实使用Hash算法来存储集合中的元素,具有很好的存储和查找能力。HashSet不是同步的,即如果有两个线程同时修改一个HashSet,必须通过代码来保证同步,例如线程的一些特性(sleep wait等等)这里不做具体介绍。所以可以说HashSet是线程不安全的。
当想HashSet中添加元素时,HashSet会调用该对象的hashCode()方法来得到改对象的hashcode值,根据该值来决定改对象的存储位置。如果有两个对象通过equals()比较返回true,但它们的hashcode返回值不相等,HashSet会把它们存储在不同的位置,依然可以添加成功。故HashSet集合判断两个元素相等的标准是两个对象通过equals()方法比较相等,并且两个对象的hashCode值也相等。看下面代码示例:
import java.util.*;
class A {
public boolean equals(Object obj) {
return true;
}
}
class B {
public int hashCode() {
return 22;
}
}
class C {
public boolean equals(Object obj) {
return false;
}
public int hashCode() {
return 24;
}
}
public class HashSetTest {
public static void main(String[] args) {
HashSet books = new HashSet();
books.add(new A());
books.add(new A());
books.add(new B());
books.add(new C());
System.out.println(books);
}
}
运行上述代码结果是[B@16, C@18, A@15db9742, A@6d06d69c] 添加了两个A对象 但是地址值是不同的。
注意Hashcode值不是元素的在内存中的地址值,HashSet通过元素的hashCode值来计算元素的地址值,从而快速定位元素。
Tips:对与HashSet中添加元素,重写equals()方法 就必须重写hashCode()方法。
如果向HashSet中添加一个可变对象,后面的程序修改了该可变对象的实例变量,导致它与集合中其他元素相同(即两个对象通过equals()返回true,hashcode返回值相等),集合中将会包含两个相同的对象。
import java.util.*;
class R {
int count;
private Object obj;
public R(int count) {
this.count = count;
}
public String toString() {
return "R[count : " + count +"]";
}
public boolean equals(Object obj) {
if(this.obj == obj)
return false;
if(obj != null && obj.getClass() == R.class){
R r = (R)obj;
return this.count == r.count;
}
// return false;
return true;
}
public int hashCode() {
return this.count;
}
}
public class HashSetTest2 {
public static void main(String[] args) throws Exception {
Set hs = new HashSet();
hs.add(new R(5));
hs.add(new R(4));
hs.add(new R(6));
hs.add(new R(-2));
System.out.println(hs);
Iterator it = hs.iterator();
// while(it.hasNext())
R first = (R)it.next();
first.count = 4;
System.out.println(hs);
hs.remove(new R(4));
System.out.println(hs);
}
}
上述代码的运行结果是:[R[count : -2], R[count : 4], R[count : 5], R[count : 6]]
[R[count : 4], R[count : 4], R[count : 5], R[count : 6]]
[R[count : 4], R[count : 5], R[count : 6]]
可以看到打印的结果,集合中含有两个count值等于4的变量,所以添加可变对象到集合中后,尽量不要在代码后面去修改其值,会产生不必要的麻烦。
2) TreeSet
查看API文档可以看到,TreeSet是SortedSet接口的实现类,所以TreeSet接口中元素处于排序状态。并且根据元素的值的大小进行升序排序,字符串比较首字母顺序。如下简单代码所示:
package Design;
import java.util.*;
public class TreeSetTest1 {
public static void main(String[] args) {
Set<Integer> test = new TreeSet();
test.add(11);
test.add(5);
test.add(9);
test.add(-1);
System.err.println(test);
Set<String> Stest = new TreeSet();
Stest.add("Kobe love ball");
Stest.add("James is suck");
Stest.add("LAL will win");
Stest.add("Beat HEAT");
System.out.println(Stest);
}
}
TreeSet采用红黑树的数据结构来存储集合元素。支持两种排序方法:自然排序和定制排序。
1.自然排序
TreeSet会调用集合元素的compareTo(Object obj)方法来比较元素之间的大小关系,然后按升序排序。
直接看例子:
package Design;
import java.util.*;
class Protocol implements Comparable {
// int obj;
int age;
public Protocol(int age) {
this.age = age;
}
public boolean equals(Object obj) {
return true;
}
public int compareTo(Object obj) {
Protocol p = (Protocol) obj;
return age > p.age ? 1 : age < p.age ? -1 : 0;
}
}
public class TreeSetTest {
public static void main(String[] args) {
Set test = new TreeSet();
Protocol p = new Protocol(5);
// test.add(new String("asd"));
test.add(p);
System.out.println(test);
System.out.println(test.add(p));
}
}
上述代码的运行结果为:[Design.Protocol@15db9742]
false
故可以看出在main函数中,是投入添加两个Protocol的引用p(对象),但因为类Protocol是先了comparable接口,重写了compareTo()方法,故TreeSet会调用compareTo方法来比较对象,上述代码返回false 即返回0 两个对象相同。注意,如果试图添加不同的类型的元素,程序就会抛异常。
Tip:如果希望TreeSet能正常运作,只能添加同一种类型的对象。
2.定制排序
自然排序是根据集合元素的大小,以升序的方式排列。但是如果想要以降序的方式排列,可以通过Comparator接口帮助,该接口里包含int compare方法。
三、总结
以上就是Java集合的部分基础知识,不足之处,请指正。