JAVA容器篇(一)学习笔记

一、摘要

本博文主要介绍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集合的部分基础知识,不足之处,请指正。




 



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值