您的位置:首页 > 编程语言 > Java开发

【java基础】——集合类(上)

2015-06-17 00:49 435 查看

一、集合框架类概述

定义:集合框架,是为了表示和操作集合而规定的一种统一的标准的体系结构。任何集合框架都包含三大内容 :对外的接口、接口的实现和集合运算的算法。接口:即表示集合的抽象数据类型。接口提供了让我们对集合所表示的内容进行单独操作的可能。
实现:也就是集合框架中接口的具体实现。实际它们就是那些可复用的数据结构。
算法:在一个实现了某个集合框架中的接口对象上完成某种有用的计算方法,例如查找、排序等等。

1、集合类的由来

面向对象语言对事物的体现都是以对象的形式来,为了方便对多个对象的操作,对对象进行存储,集合就是存储对象最常用的一种方式。

2、集合和数组的异同

相同之处:集合和数组都是容器。
集合和数组中存储的都是对象的引用(内存地址值)。不同之处:数组虽然也可以存储对象,但长度是固定的;集合长度的可变的。
数组只能存储一种类型的对象,集合可以存储任意类型的对象。
数组中可以存储基本数据类型,集合只能存储对象。

3、集合框架体系的内容

java集合框架的体系内容可以见如下图:java集合框架图简析如下:集合接口:6个接口,(短虚线表示),表示不同类型的集合,是集合框架的基础。
抽象类:5个抽象类,(长虚线表示),对几个接口的部分实现,可扩展为自定义集合类。
实现类:8个实现类,(实现表示),对接口的具体实现。在很大程度上,一旦理解了接口,也就理解了框架,虽然总要创建接口特定的实现,但访问实际集合的方法应该限制在接口方法的使用上,因此,Java集合类允许我们更改基本数据结构而不必改变它的代码。Collection接口是一组允许重复的对象。
Set接口继承了Collection,但不允许重复,元素是无序的,使用自己内部的一个排列机制。
List接口继承了Collection,允许重复,元素是有序的,以元素安插的顺序来放置元素,不会重新排列。
Map接口是一组成对的键-值对象,Map中的键是唯一的,不允许重复,拥有自己的内部排列机制。
注:容器中的元素都为Object类型,从容器取得元素时,必须把它转换成原来的类型。

二、Collection<E>接口

当用于表示任何对象或者元素组,想要尽可能以常规 方式处理一组元素时,就使用这一接口。Collection下有两个常用子接口:List<E>(列表)、Set<E>(集)。

1、Collection接口中的常用方法:

a、添加方法boolean add(E e) 添加一个元素。add方法的参数类型是 Object 。以便于接收任意类型对象。boolean
addAll(Collection<? extends E> c) 添加另一集合内所有元素b、删除方法boolean remove(Object
o);删除一个元素boolean
removeAll(Collection<?> c)仅移除本集合中另一集合也有的元素,即移除本集合中与另一集合的交集void
clear();清空集合c、判断方法boolean contains(Object
o) 判断是否包含某个元素boolean
containsAll(Collection<?> c)判断是否包含另一集合中的所有元素boolean
isEmpty()判断集合是否为空 //其实它是在调用size方法d、获取方法Iterator<E> iterator()迭代。返回在此集合的元素上进行迭代的迭代器。int
size()获取集合长度boolean
retainAll(Collection<?> c)仅保留此集合中另一集合也有的元素,即保留本集合与另一集合的交集e、Collection转换为Object数组Object[] toArray() :返回一个内含集合所有元素的arrayObject[]
toArray(Object[] a) :返回一个内含集合所有元素的array。运行期返回的array和参数a的型别相同,需要转换为正确型别。此外,我们还可以把集合转换成其它任何类型的数组。但是,我们不能直接把集合转换成基本数据类型的数组,因为集合必须持有对象。以下是对Collection基本方法的演示:
import java.util.*;
/*Collection集合常用方法演示*/
class  CollectionDemo
{
	public static void main(String[] args) 
	{
		method_get();
	}
	public static void method_get()
	{
		Collection list1 = new ArrayList();
		/*==================1、添加方法演示==================*/
		//添加元素。add()
		list1.add("huangxiang01");
		list1.add("huangxiang02");
		list1.add("huangxiang03");
		list1.add("huangxiang04");
		//添加另一集合的所有元素。addAll()
		Collection list2 = new ArrayList();
		list2.add("huang55");
		list2.add("huang56");
		list2.add("huang57");
		list2.add("huangxiang04");
		//将list2集合的中元素全部添加到list1集合中。
		//list1.addAll(list2);
		
		/*==================2、删除方法演示==================*/
		//删除元素。remove()
		//list1.remove("huangxiang01");
		//删除本集合中另一集合也有的元素
		//list1.removeAll(list2);
		//清空集合
		//list1.clear();
		
		/*==================3、判断方法演示==================*/
		//判断是否包含某个元素
		Sop(list1.contains("huangxiang03"));
		//判断是否包含另一集合中的所有元素
		Sop(list1.containsAll(list2));
		//判断集合是否为空
		Sop(list1.isEmpty());
		
		/*==================4、获取方法演示==================*/
		//迭代器
		Iterator it = list1.iterator();
		while(it.hasNext()){
			Sop(it.next());
		}
		//获取集合长度
		Sop(list1.size());
		//获取本集合与另一集合的交集
		Sop(list1.retainAll(list2));
		
		/*==================5、数组转换方法演示==================*/
		//返回一个内含集合所有元素的array
		list1.toArray();
		//
	}
	public static void Sop(Object obj){
		System.out.println(obj);
	}
}

2、迭代器Iterator

迭代器是取出集合中元素的一种方式,Collection中实现了iterator()方法,所以其每一个子集合都具备迭代器。
a、迭代器常见操作:hasNext():如果有下一个元素,返回真
next():取出下一个元素
remove():移除
注意:在迭代循环中,next每调用一次,就要用hasNext()判断一次。b、迭代注意事项迭代器在Collection接口中是通用的,他替代了Vector类中的枚举。
迭代器的next()方法是自动向下取元素,要避免出现NoSuchElementException。
迭代器的next()方法返回值类型是Object,要注意类型转换。

三、List<E>接口

List接口继承了Collection结构以定义一个允许重复项的有序集合。该接口不但能够对列表的一部分进行处理,还添加了面向位置的操作。凡是可以对角标进行操作的方法都是该体系特有的方法。

1、List接口的常用子类对象

ArrayList:底层的数据结构使用的是数组。特点:查询速度很快。但是增删稍慢,线程不同步。
LinkedList:底层使用的是链表数据结构。特点:增删速度很快。查询较慢。
Vector:底层是数组数据结构。线程同步。被ArrayList替代。

2、List接口的特有方法

void add(int index,E element)在列表的指定位置插入指定元素。boolean
addAll(int index, Collection<? extends E> c) 将指定 collection 中的所有元素都插入到列表中的指定位置。E
remove(int index) 移除列表中指定位置的元素。E
set(int index, E element) 用指定元素替换列表中指定位置的元素,返回以前在指定位置的元素。E
get(int index) 返回列表中指定位置的元素。List<E>
subList(int fromIndex, int toIndex) 返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分列表。ListIterator<E>
listIterator() 返回此列表元素的列表迭代器。ListIterator<E>
listIterator(int index) 从列表的指定位置开始返回列表中元素的列表迭代器。

3、ArrayList类

ArrayList类封装了一个动态再分配的Object[]数组。每一个ArrayList对象都有一个capacity,这个capacity表示存储列表中元素的数组的容量。当元素添加满时,它会自动扩容。在jdk1.6中,自动扩容为增加i*3/2+1,在1.7及1.8中,为1.5倍扩容。
下面是ArrayList的一些常用方法演示:
import java.util.*;
//ArrayList 最基本的用法
public class ArrayListTest1{
	public static void main(String[]args){
		//如何创建对象
		List<Integer> list = new ArrayList<Integer>();
		//向ArrayList中添加元素
		list.add(25);
		list.add(26);
		list.add(12);
		list.add(28);
		//得到Arraylist中添加了多少个元素
		System.out.println(list.size());
		System.out.println("===================华丽的分割线================");
		//如何得到集合当中的第几个元素
		Integer num = list.get(1);
		System.out.println(num);
		System.out.println("===================华丽的分割线================");
		//如何遍历ArrayList。
		//第一种方法:for循环
		for(int i = 0;i < list.size();i++){
			System.out.println(list.get(i));
		}
		System.out.println("===================华丽的分割线================");
		//第二种方法,迭代器
		Iterator<Integer> it = list.iterator();
		while(it.hasNext()){
			Integer data = it.next();
			System.out.println(data);
		}
		System.out.println("==========================华丽的分割线==========================");
		//第三种方法:foreach循环
		for(Integer i : list)
			System.out.println(i);
	}	
}
import java.util.*;
//ArrayList提供了remove(int index),remove(Object obj)两个方法删除
public class ArrayListTest2{
	public static void main(String[] args){
		ArrayList<Integer> list = new ArrayList<>(5);
		/*list.add(1);
		list.add(2);
		list.add(3);
		list.add(4);
		list.add(5);*///list集合中的添加方法,逐个添加
		Collections.addAll(list,1,2,3,4,5);//Collections提供的addAll方法
		//addAll(list,1,2,3,4,5);//自定义的批量添加addAll方法
		System.out.println(list);
		//删除元素:方法1
		list.remove(2);//明确的删除第几个元素
		System.out.println(list);
		System.out.println("==================华丽的分割线===================");
		//删除元素:方法2
		list.remove(new Integer(4));//明确的删除哪一个元素
		System.out.println(list);
		System.out.println("====================华丽的分割线=================");
		//删除所有元素:用循环
		/*while(list.size()!=0)
			list.remove(0);
		System.out.println(list);*/
		//删除所有元素:用clear()方法
		list.clear();
		System.out.println(list);
	}
	public static void addAll(List<Integer> list,Integer...data){
		for(Integer i : data)
			list.add(i);
	}
}
import java.util.*;
//remove(Object obj)是如何找到元素的,如何删除你的元素的
public class ArrayListTest3{
	public static void main(String[] args){
		ArrayList<Integer> list = new ArrayList<>();
		Integer i1 = new Integer(5);
		Integer i2 = new Integer(5);
		list.add(i1);
		System.out.println(list.size());//结果是1
		list.remove(i2);
		System.out.println(list.size());//结果是0
		//结果:说明ArrayList的remove(Object obj) 完全尊重equals比较返回的结果。
		System.out.println("===================华丽的分割线====================");
		ArrayList<Teacher> list2 = new ArrayList<>();
		Teacher tea1 = new Teacher("zhangsan",25);
		Teacher tea2 = new Teacher("zhangsan",25);
		list2.add(tea1);
		System.out.println(list2.size());//结果为1
		list2.remove(tea2);
		System.out.println(list2.size());//结果为1
		//在复写之前结果为1,即相同的元素没有被删除。这是因为在Object中的eaquls方
		//法其实就是==运算
		//复写equals方法之后,相同的元素被删除。
	}
} 
class Teacher{
	private String name;
	private int age;
	
	public Teacher(String name,int age){
		this.name = name;
		this.age = age;
	}
	@Override
	public boolean equals(Object obj){
		System.out.println("我被执行啦");
		//做一些健壮性判断
		if(obj == null) return false;
		if(!(obj instanceof Teacher)) return false;
		if(obj == this) return true;
		Teacher t1 = this;
		Teacher t2 = (Teacher)obj;
		return t2.name.equals(t2.name) && (t1.age == t2.age);
	}
}
import java.util.*;
public class ArrayListTest4{
	public static void main(String[] args){
		List<Integer> list = new ArrayList<>();
		Collections.addAll(list,1,2,3,4,5);
		//需求:删除所有小于3的数
		Iterator<Integer> it = list.iterator();
		/*
		 java.util.ConcurrentModificationException并发修改异常。
		 按照下面这种写法会发生该异常。在迭代器遍历ArrayList的过程当中,绝对不允许
		 对集合整体进行任何添加删除操作。(除了删除不成功的)
		while(it.hasNext()){
			Integer num = it.next();
			if(num<3)
				list.remove(num);
		}
		*/
		while(it.hasNext()){
			Integer num = it.next();
			if(num<3)
				it.remove();
		}
		System.out.println(list.size());
	}
}
//模拟ArrayList的主要方法底层实现
public class ArrayListTest5{
	public static void main(String[] args){
		MyList list = new MyList();
		list.add(1);
		list.add(2);
		list.add(3);
		list.add(4);
		System.out.println(list.getSize());
	}
}
class MyList{
	private Object[] data;
	private int size;//用户存放了多少元素进来
	
	//根据用户指定的容量,初始化底层的数组的构造方法
	public MyList(int length){
		data = new Object[length];
	}
	//默认的构造方法,它共享了有參的构造方法,默认10个空
	public MyList(){
		this(10);
	}
	//用来得到已经存放的元素个
	public int getSize(){
		return size;
	}
	
	//得到第几个元素的方法
	public Object get(int i){
		return data[i];
	}
	//添加元素的方法
	public void add(Object obj){
		//如果底层的数组存储空间已经满了
		if(data.length == size){
			Object[] temp = new Object[size*3/2+1]; //找到一个更大的新筐
			System.arraycopy(data,0,temp,0,size);//将老筐里面的棒子放到新筐里
			data = temp;//背上新筐(老筐留给收垃圾的)
		}
		data[size++] = obj;
	}
	//删除第几个元素的方法
	public void remove(int x){
		System.arraycopy(data,x+1,data,x,size-x-1);
		size--;
		/*
			0 1 2 3 4   要删除的是下标2,那么其实就是从下标3开始向下标2复制元素 
			0 1 3 4		总共复制5-2-1.
		*/
	}
	//删除指定的那个元素的方法
	public void remove(Object obj){
		for(int i = 0;i<size;i++){
			if(obj.equals(data[i]))
				remove(i);
		}
	}
}

4、LinkedList类

在LinkedList类中,添加了一些处理两端元素的方法。void addFirst(Object o): 将对象o添加到列表的开头void
addLast(Object o):将对象o添加到列表的结尾Object
getFirst(): 返回列表开头的元素Object
getLast(): 返回列表结尾的元素Object
removeFirst(): 删除并且返回列表开头的元素Object
removeLast():删除并且返回列表结尾的元素LinkedList():
构建一个空的链接列表LinkedList(Collection
c): 构建一个链接列表,并且添加集合c的所有元素通过对这些新方法的使用,我们可以轻松的把 LinkedList当成一个栈堆。队列、或者其它面向端点的数据结构。
在JDK1.6以后,出现了替代方法。offFirst();替代addFirstoffLast();替代addLastpeekFirst();替代getFirstpeekLast();替代getLastpollFirst();替代removeFirstpollLast();替代removeLast下面举例一个使用LinkedList模拟一个栈堆或队列的数据结构。
/*
使用LinkedList模拟一个堆栈或者队列数据结构。

堆栈:先进后出  如同一个杯子。
队列:先进先出 First in First out  FIFO 如同一个水管。

*/
import java.util.*;

class LinkedListTest
{
	public static void main(String[] args) 
	{
		LinkedList l=new LinkedList();
		l.addFirst("java01");
		l.addFirst("java02");
		l.addFirst("java03");
		l.addFirst("java04");
		l.addFirst("java05");
	
		//堆栈输出
	//	stack(l);
		
		//队列输出
		queue(l);
	}

	//堆栈
	public static void stack(LinkedList l)
	{
		while (!l.isEmpty())
		{
			sop(l.removeFirst());
		}
	}
	//队列
	public static void queue(LinkedList l)
	{
		while(!l.isEmpty())
		{
			sop(l.removeLast());
		}
	}

	//输出
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}

5、ListIterator

ListIterator接口继承了Iterator接口,是List集合的特有的。以支持添加和更改底层集合中的元素。还支持双向访问。ListIterator没有当前位置。光标位于调用previous和next方法的返回值之间。
ListIterator特有的方法:add(obj); 将obj添加到当前位置的前面set(obj); 用obj替代next或者previous方法访问的上一个元素。如果上次调用后列表结构被修改了。将抛出异常。hasPrevious(); 判断前面有没有元素previous(); 返回上一个元素对象注:“正常情况下,不用ListIterator改变某次遍历集合元素的方向 — 向前或者向后。虽然在技术上可以实现,但previous() 后立刻调用next(),返回的是同一个元素。把调用 next()和previous()的顺序颠倒一下,结果相同。”“我们还需要稍微再解释一下 add() 操作。添加一个元素会导致新元素立刻被添加到隐式光标的前面。因此,添加元素后调用 previous() 会返回新元素,而调用 next() 则不起作用,返回添加操作之前的下一个元素。”

6、Vector类

该类中带有elements的方法都是该类特有的方法。
Vector类有特有的元素取出方式:枚举是其取出元素的方式,因为其名称及方法名过长,被迭代器给取代了。
该类的特有方法如下:addElement(obj);//添加元素,相当于add(obj);Enumerationelements();//Vector特有取出方式(枚举)hasMoreElements();//相当于Iterator的hasNext()方法nextElements();//相当于Iterator的next()方法Vector类应用举例:
Vector v=new Vector();
	for(Enumeration e=v.elements();e.hasMoreElements();)
{
	System.out.println(e.nextElements());
}

四、Set<E>接口

Set接口继承了Collection接口,而且它不允许集合中存在重复项,每个具体的的Set实现类依赖添加的对象的equals()方法来检查其唯一性,Set接口没有引入新方法,其方法和Collection一样,不过行为不同。了解Set类,首先要对散列表(hash table也称哈希表)和树集有所了解。

1、散列表(哈希表)

众所周知,有一种数据结构可以快速的查找所需要的对象,这就是散列表,散列表为每个对象计算一个整数,称为散列码(hash code)。散列码是由对象的实例域产生的一个整数。更准确地说,具有不同数据域的对象将产生不同的散列码。如果我们要自定义类,就要负责实现这个类的hashCode方法,另外自己实现的hashCode方法英语equals方法兼容,即如果a.equals(b)的值为true,则a与b必须具有相同的散列码。在java中,HashSet是基于散列表的集。

2、树集

树集是一个有序集合。可以以任意顺序将元素插入到集合中。在对集合进行遍历时,每个值将自动的按照排序后的顺序呈现。在java中,TreeSet的底层结构是树结构。

3、Set概述

Set<E>:元素是无序的,存入和取出的顺序不一定一致。元素不可以重复!主要实现类有HashSet和TreeSet。HashSet:底层数据结构是哈希表,线程不同步。其保证元素唯一性的原理是:判断元素的hashCode是否相同,如果相同会继续判断元素的equals方法。
TreeSet:可以对Set集合中的元素进行排序。默认按照字母的自然顺序排序。底层数据结构是二叉树。保证元素唯一性的依据是:compareTo方法返回true。当compareTo方法无法满足需求时,可以采用自定义比较器,实现Comparator接口并覆盖其中的compare()方法来实现。

4、Comparable接口和Comparator接口

在“集合框架”中有两种比较接口:Comparable接口和Comparator接口。像String和Integer等Java内建类实现 Comparable接口以提供一定排序方式,但这样只能实现该接口一次。对于那些没有实现Comparable接口的类、或者自定义的类,您可以通过 Comparator接口来定义您自己的比较方式。Compareable接口在java.lang包中,Comparable接口适用于一个类有自然顺序的时候。假定对象集合是同一类型,该接口允许您把集合排序成自然顺序。a、int compareTo(Object o): 比较当前实例对象与对象o,如果位于对象o之前,返回负值,如果两个对象在排序中位置相同,则返回0,如果位于对象o后面,则返回正值在 Java 2 SDK版本1.4中有二十四个类实现Comparable接口。下表展示了8种基本类型的自然排序。虽然一些类共享同一种自然排序,但只有相互可比的类才能排序。
排序
BigDecimal,BigInteger,Byte, Double, Float,Integer,Long,Short按照数字大小排序
Character按 Unicode 值的数字大小排序
String按字符串中字符 Unicode 值排序
利用Comparable接口创建您自己的类的排序顺序,只是实现compareTo()方法的问题。通常就是依赖几个数据成员的自然排序。同时类也应该覆盖equals()和hashCode()以确保两个相等的对象返回同一个哈希码。b、Comparator接口若一个类不能用于实现java.lang.Comparable,或者您不喜欢缺省的Comparable行为并想提供自己的排序顺序(可能多种排序方式),你可以实现Comparator接口,从而定义一个比较器。int compare(Object o1, Object o2): 对两个对象o1和o2进行比较,如果o1位于o2的前面,则返回负值,如果在排序顺序中认为o1和o2是相同的,返回0,如果o1位于o2的后面,则返回正值“与Comparable相似,0返回值不表示元素相等。一个0返回值只是表示两个对象排在同一位置。由Comparator用户决定如何处理。如果两个不相等的元素比较的结果为零,您首先应该确信那就是您要的结果,然后记录行为。”boolean equals(Object obj): 指示对象obj是否和比较器相等。“该方法覆写Object的equals()方法,检查的是Comparator实现的等同性,不是处于比较状态下的对象。”

5、HashSet类

a、概述:HashSet实现了Set接口,不保证Set的迭代顺序,允许使用null元素。该类的实现是不同步的。该类的构造方法如下:HashSet():构造一个新的空 set,其底层 HashMap 实例的默认初始容量是 16,加载因子是 0.75。HashSet(Collection<? extendsE> c):构造一个包含指定
collection 中的元素的新 set。HashSet(int initialCapacity): 构造一个新的空 set,其底层 HashMap 实例具有指定的初始容量和默认的加载因子(0.75)。HashSet(int initialCapacity, float loadFactor):构造一个新的空 set,其底层 HashMap 实例具有指定的初始容量和指定的加载因子。
b、Hashset类的实现:HashSet是基于HashMap实现的。其底层采用HashMap来保存元素,查看HashSet的源代码我们可以发现,HashSet的绝大部分方法都是通过调用HashMap的方法来实现的。因此HashSet和HashMap在本质上是相同的。
c、HashSet实现自定义类的元素唯一性的代码实例:
import java.util.*;
/*
需求:往HashSet中存入自定义对象。姓名和年龄相同是同一个人。为重复元素。应去除。
思路:1、对人进行描述,将人的一些属性等封装
      2、定义一个HashSet集合,存储对象
      3、取出。
*/
public class HashSetTest2{
	public static void main(String[]args){
		//创建一个HashSet集合
		HashSet<Person> hs = new HashSet<Person>();
		//向集合中添加元素,这里添加了两个相同元素
		hs.add(new Person("zhangsan",25));
		hs.add(new Person("lisi",25));
		hs.add(new Person("wangwu",25));
		hs.add(new Person("zhangsan",25));
		hs.add(new Person("wangwu",25));
		//返回迭代器
		Iterator<Person> it = hs.iterator();
		//迭代取出元素
		while(it.hasNext()){
			Person p = it.next();
			System.out.println(p.getName()+"......."+p.getAge());
		}
	}
}
//自定义类
class Person{
	private String name;
	private int age;
	//构造方法初始化
	public Person(String name,int age){
		this.name = name;
		this.age = age;
	}
	public String getName(){
		return name;
	}
	public int getAge(){
		return age;
	}
	//复写hashCode方法
	@Override
	public int hashCode(){
		return name.hashCode()+age;
	}
	//复写Obeject类中的equals方法
	public boolean equals(Object obj){
		//健壮性判断
		if(obj == null) return false;
		if(!(obj instanceof Person)) return false;
		if(obj == this)  return true;
		Person p = (Person)obj;
		//这里的equals方法是字符串的equals方法。
		return this.name.equals(p.name) && this.age == p.age;
	}
	
}

6、TreeSet

a、TreeSet的构造方法摘要TreeSet():构造一个新的空 set,该 set 根据其元素的自然顺序进行排序。TreeSet(Collection<? extendsE> c):构造一个包含指定
collection 元素的新 TreeSet,它按照其元素的自然顺序进行排序。TreeSet(Comparator<? superE> comparator):构造一个新的空
TreeSet,它根据指定比较器进行排序。TreeSet(SortedSet<E> s):构造一个与指定有序 set
具有相同映射关系和相同排序的新 TreeSet。
b、下面通过一个实例来描述TreeSet实现排序的两种方式:
import java.util.*;
/*
	创建两个Item对象的树集。第一个按照部件编号排序,这是Item对象的默认顺序,
	第二个通过使用一个定制的比较器来按照描述信息排序。
*/
public class TreeSetTest1{
	public static void main(String[] args){
		//第一个TreeSet集合,按照默认排序编号进行排序。compareTo()
		SortedSet<Item> parts = new TreeSet<Item>();
		parts.add(new Item("Tosater",1234));
		parts.add(new Item("Widget",4562));
		parts.add(new Item("Modem",9912));
		System.out.println(parts);
		//第二个Set集合,按照自定义比较器按照描述信息排序
		SortedSet<Item> sortByDescription = new TreeSet<Item>(new 
			Comparator<Item>(){
				//匿名内部类实现Comparator接口
				public int compare(Item a,Item b){
					String descrA = a.getDescription();
					String descrB = b.getDescription();
					return descrA.compareTo(descrB);
				}
			});
			//打印排序后的结果
			sortByDescription.addAll(parts);
			System.out.println(sortByDescription);
	}
}
/*
	创建一个待描述信息和部件编号的类
*/
class Item implements Comparable<Item>{
	private String description;
	private int partNumber;
	/**
		构造器初始化
		@aDescription  Item的description
		@aPartNumber   Item的部件编号(part number)
	*/
	public Item(String aDescription,int aPartNumber){
		description = aDescription;
		partNumber = aPartNumber;
	}
	/**
		获取Item的描述信息
		@return description 返回值
	*/
	public String getDescription(){
		return description;
	}
	@Override
	public String toString(){
		return "[description=" + description + ",partNumber" + partNumber+"]";
	}
	@Override
	public boolean equals(Object otherObject){
		//健壮性判断
		if(this == otherObject) return true;
		if(otherObject == null) return false;
		if(getClass() != otherObject.getClass()) return false;
		
		Item other = (Item)otherObject;
		return 
		description.equals(other.description) && partNumber == other.partNumber;
	}
	//复写hashCOde()方法
	@Override
	public int hashCode(){
		return 13*description.hashCode()+17*partNumber;
	}
	//复写compareTo方法
	@Override
	public int compareTo(Item other){
		return partNumber - other.partNumber;
	}
}
c、TreeSet的小练习(自定义比较器)
import java.util.*;
/*
按照字符串长度排序
分析:字符串本身具有比较性,但不符合题目的需求,所以需要重写一个比较器。
*/
public class TreeSetTest4{
public static void main(String[] args){
TreeSet<String> set = new TreeSet<>(new strLenComparetor());

set.add("dadadwd");
set.add("dasd");
set.add("dsd");
set.add("ddsdsdwd");
set.add("daddsdswedcs");
set.add("dsddd");
set.add("da");

Iterator<String> it = set.iterator();

while(it.hasNext()){
System.out.println(it.next());
}
}
}class strLenComparetor implements Comparator{
public int compare(Object o1,Object o2){
//将Object型强转为String型
String s1 = (String)o1;
String s2 = (String)o2;
//比较
int num = new Integer(s1.length()).compareTo(new Integer(s2.length()));
//当比较结果为0时,将再次进行比较,以保证比较的准确性
if(num == 0)
s1.compareTo(s2);
//不为0时,返回num的值
return num;
}
}
d、TreeSet实现两种比较方式的应用实例二:
import java.util.*;
public class TreeSetTest3{
	public static void main(String[] args){
		TreeSet<Student> set = new TreeSet<>(new MyCompare());
		set.add(new Student("zhangsan",25));
		set.add(new Student("lisi",23));
		set.add(new Student("wangwu",30));
		set.add(new Student("zhaoliu",19));
		set.add(new Student("zhaoliu2",19));
		set.add(new Student("zhuqi",28));
		set.add(new Student("zhuqi2",28));
		
		Iterator<Student> it = set.iterator();
		
		while(it.hasNext()){
			Student stu = it.next();
			System.out.println(stu.getName()+"........"+stu.getAge());
		}
	}
}
//自定义比较器
class MyCompare implements Comparator{
	public int compare(Object o1,Object o2){
		Student s1 = (Student)o1;
		Student s2 = (Student)o2;
		int num = s1.getName().compareTo(s2.getName());
		if(num == 0)
			return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
		return num;
	}
}
//继承Compareable,让其具有比较性
class Student implements Comparable{
	private String name;
	private int age;
	
	public Student(String name,int age){
		this.name = name;
		this.age = age;
	}
	@Override
	public int compareTo(Object obj){
		//健壮性判断
		if(obj == null) return -1;
		if(obj == this) return 0;
		if(!(obj instanceof Student)) 
			throw  new RuntimeException("类型不一致");
		Student s = (Student)obj;
		System.out.println(this.name+"......compareTo...."+s.name);
		if(this.age>s.age) return 1;
		if(this.age==s.age) {
			this.name.compareTo(s.name);
		}
		return -1;
	}
	
	public String getName(){
		return name;
	}
	public int getAge(){
		return age;
	}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: