黑马程序员——Java集合框架(一)之迭代器、Collection层次结构等

-----------android培训java培训、java学习型技术博客、期待与您交流!------------

集合框架概述

一、什么是集合框架 

 1.什么是集合?

  集合是指把具有相同性质的一类东西汇聚成一个整体,简单说就是指存储数据的一个容器。集合存储的是对象的引用(地址)。

 2.框架是什么?

  框架是指一个基本概念的结构,在此结构上可以根据具体问题扩展、安插更多的组成部分,从而更迅速和方便地构建完整的解决问题的方案。 就好比建一栋大厦,那么最初的地基水泥土结构就可以理解为框架。在Java中框架可以理解为类库组成的架构。

 那么什么是集合框架呢?集合框架是指为表示和操作集合而规定的一种统一的标准的体系结构,该体系结构包含两个部分,一个是接口,一个是类。任何集合框架都包含三大块内容:对外的接口、接口的实现和对集合运算的算法。

 接口:是代表集合的抽象数据类型。接口允许集合独立操纵其代表的细节。在面向对象的语言,接口通常形成一个层次。

 实现(类):是集合接口的具体实现。从本质上讲,它们是可重复使用的数据结构。

 算法:是实现集合接口的对象里的方法执行的一些有用的计算,例如:搜索和排序。这些算法被称为多态,那是因为相同的方法可以在相似的接口上有着不同的实现。

 问题思考:为什么集合框架中会出现接口?

  答:因为集合框架中的很多类的功能是相似的,因此用接口来规范类。


二、集合框架体系

 集合框架体系是由许多集合类或接口等构成的架构关系图,如下所示:


 在这个集合框架图中,可以划分成五个部分,分别为Iterator迭代器、Collection层次结构、Map层次结构、Comparable与Comparator、Collections与Arrays。

 Iterator迭代器:用来对集合中的对象进行取出,其提供了判断、取出和删除方法。Iterator有一个重要的子接口ListIterator,该接口提供了更多操作对List集合进行操作。

 Collection层次结构:Collection接口是该层次结构的根接口,该接口的所有子接口或实现子类集合都可以用Iterator迭代器进行取出。Collection的常见子接口有两个,即为List和Set,其中List集合可以用ListIterator迭代器取出。List接口的主要实现子类有ArrayList和LinkedList等,Set接口的主要实现子类有HashSet和TreeSet等。

 Map层次结构:Map接口是该层次结构的根接口。Map集合是用来存取键值对的集合,即一对一对的往集合里存储,但需保证键的唯一性。Map集合提供了keySet()方法用来把所有的键存储到Set集合,提供了entrySet()方法用来把所有键值对的关系存储到Set集合,因此也间接使用了Iterator迭代器进行存储。Map的实现子类主要有HashMap和treeMap。

 Comparable与Comparator:都是用来实现集合中元素的比较、排序的。Comparable 是在集合内部定义的方法实现的排序,而Comparator 是在集合外部实现的排序。

 Collections与Arrays:Collections是专门用于对集合进行操作的工具类,Arrays是专门用于操作数组的工具类。工具类中的方法都是静态方法。

 问题思考:为什么会出现这么多集合?

  答:因为每一个集合对数据的存储方式都有不同,该存储方式也称数据结构。


Iterator迭代器

一、什么是迭代器

 迭代器是指用于取出集合元素的方式。


二、Iterator迭代器的理解

 1.迭代器被封装为一个对象,即Iterator接口。

  由于迭代器需要定义多个功能才能完成集合元素的取出,其中包括判断和获取等功能,不足以用一个函数进行描述,因此被封装成对象。

 2.Iterator迭代器的具体实现类定义在集合内部。

  对于不同的集合,迭代器的取出方式也不相同,由于对集合元素进行取出操作是在集合内部完成,因此迭代器以内部类的方式定义在集合内部更加适合,即迭代器成为集合的一部分。

 3.每个集合迭代器的具体实现类都存在着共性内容,如获取、判断和删除,因此向上抽取就有了Iterator接口。每个集合可通过调用iterator()方法获取迭代器的具体实现类对象,通过该对象完成对该集合元素的操作。


三、Iterator迭代器的常见操作

 1.判断集合内是否有元素存在:

  boolean hasNext():如果仍有元素可以迭代,则返回 true。

 2.获取集合内的元素:

  E next():返回迭代的下一个元素。

  注:该方法会自动向下返回集合内元素,且返回的类型为Object。如果用next()方法取出时没有元素,则会发生NoSuchElementException。如果要使用元素本类对象类型,需对其进行强制类型转换。

 3.删除集合内的元素:

  void remove():从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。

 注:迭代器在Collcection接口中是通用的,它替代了Vector类中的Enumeration(枚举)。


四、ListIterator(列表迭代器)

 1.什么是ListIterator?

  ListIterator是Iterator接口的子接口,专门用于对List集合的元素进行操作。

 2.定义ListIterator的目的

  在对集合元素进行迭代时,不可以通过集合对象的方法操作集合中的元素,否则会发生ConcurrentModificationException异常。所以在迭代时,只能用迭代器的方法操作集合中元素,但是Iterator的方法是有限的,只能进行判断、取出和删除的操作。

  为了使迭代器提供更多的方法进行操作集合中元素,于是定义了一个ListIterator接口,该接口继承了Iterator接口的方法,也定义了自己特有的一些方法,如增加、修改等,这样对集合元素就有了更广泛的操作。

  注:ListIterator虽然提供了比Iterator更广泛的操作,但是只能用于对List集合的操作,因为只有List集合的元素具有索引。

 3.ListIterator的常见特有方法

  a)添加集合中的元素:

   void add(E e):将指定的元素插入列表。

  b)修改集合中的元素:

   void set(E e):用指定元素替换 next 或 previous 返回的最后一个元素。

  c)逆向遍历列表:

   boolean hasPrevious():如果以逆向遍历列表,列表迭代器有多个元素,则返回 true。


五.获取迭代器方式

 1.获取Iterator迭代器对象

  a)创建一个Collection集合。

  b)通过调用iterator()方法获取该集合的迭代器对象。

  示例:

   HashSet hs=new HashSet();//创建一个Collection集合

   Iterator i=hs.iterator();//获取该集合的迭代器对象

 2.获取ListIterator迭代器对象

  a)创建一个List集合。

  b)通过调用listIterator()方法获取该集合的迭代器对象。

  示例:

   ArrayList al=new ArrayList();//创建一个List集合

   ListIterator li=al.listIterator();//获取迭代器对象


六、示例

import java.util.*;

/*
迭代器示例:
*/
class IteratorDemo 
{
	public static void main(String[] args) 
	{
		ArrayList al=new ArrayList();//创建一个集合

		//添加元素
		al.add("zhangsan");
		al.add("lisi");
		al.add("wangwu");

		//第一种方式
		Iterator i=al.iterator();//获取该集合的迭代器对象,用以取出集合中的元素

		while (i.hasNext())//判断元素
		{
			Object obj=i.next();//取出元素
			System.out.println("方式1:"+obj);//打印元素
		}
		
//		for (Iterator i=al.iterator();i.hasNext() ; )
//		{
//			Object obj=i.next();
//			System.out.println("obj="+obj);
//		}


		//第二种方式
		for (ListIterator li=al.listIterator();li.hasNext(); )
		{
			Object obj=li.next();
			System.out.println("方式2:"+obj);
		}
	}
}
 程序运行后的结果如下图:



Collection层次结构

一、Collection接口

 1.Collection概述

  Collection接口是该层次结构的根接口,该接口的所有子接口或实现子类集合都可以用Iterator迭代器进行取出。Collection有两个常见子接口,即为List和Set,其中List集合可以用ListIterator迭代器取出。List接口的主要实现子类有ArrayList和LinkedList等,Set接口的主要实现子类有HashSet和TreeSet等。Collection层次结构图如下:

  Collection

   |--List :元素是有序的,元素可以重复,因为该集合体系有索引。

    |--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快,但是增删稍慢,且线程不同步。

    |--LinkedList:底层使用的是链表数据结构。特点:增删速度很快,查询稍慢。

    |--Vector:底层是数组数据结构。线程同步,但已被ArrayList替代了。

   |--Set :元素是无序的(存入和取出的顺序不一定一致),元素不可以重复。

    |--hashSet:底层数据结构是哈希表。

    |--treeSet:底层数据结构是二叉树。可以对Set集合中的元素进行排序,默认排序方式为自然排序,也成字典排序。

 2.共性方法

  a)添加元素

   boolean add(E  e):add方法的参数类型是Object。以便于接收任意类型对象。

   boolean addAll(Collection<? extends E> c):将指定 collection 中的所有元素都添加到此 collection 中。尖括号内容表示泛型,后面会介绍。

  b)删除元素
   boolean remove(Object  obj):从此 collection 中移除指定元素的单个实例。
   boolean removeAll(Collection<?> c):移除此 collection 中那些也包含在指定 collection 中的所有元素,即调用者只保留另一集合中没有的元素。
   void clear():移除此 collection 中的所有元素,即清空集合。
  c)判断元素
   boolean contains(Object  obj):如果此 collection 包含指定的元素,则返回 true。
   boolean isEmpty():如果此 collection 不包含元素,则返回 true。判断是否为空。
  d)获取个数,集合长度
   int size():返回此 collection 中的元素数。
  e)取交集
   boolean retainAll(Collection<?> c):仅保留此 collection 中那些也包含在指定 collection 的元素,即调用者只保留两集合的共性元素。


二、List集合

 1.概述

  List集合的所有元素都具有索引,因此元素是有序的 ,是可以重复的。List继承了Collection, 其中List集合不仅可以用Iterator迭器方式取出,同时还可以用ListIterator迭代器方式取出。List接口的主要实现子类有ArrayList和LinkedList等。其框架关系如下: 

  |--List :元素是有序的,元素可以重复,因为该集合体系有索引。

    |--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快,但是增删稍慢,且线程不同步。

    |--LinkedList:底层使用的是链表数据结构。特点:增删速度很快,查询稍慢。

    |--Vector:底层是数组数据结构。线程同步,但已被ArrayList替代了。

  注:开发中,如果涉及到了频繁的增删操作,用LinkedList。如果涉及到了增删操作,但不频繁,可以用ArrayList,也可以用LinkedList。如果涉及到增删操作,也涉及到查询,建议使用ArrayList,因为频繁的增删操作不多见。如果不能确定使用哪一个,就选用Arraylist。

 2.List集合特有方法

  a)添加元素:

   boolean add(int index,E element):在列表的指定位置插入指定元素。

   boolean addAll(int index,Collection<? extends E> c):将指定 collection 中的所有元素都插入到列表中的指定位置。

  b)删除元素:

   E remove(int index):移除列表中指定位置的元素。

   注:先获取返回该元素后再移除,不一定需要对返回的该元素进行操作,如打印等,后面方法中同理。

  c)修改元素:

   E set(int index,E element):用指定元素替换列表中指定位置的元素。

  d)获取元素:

   E get(int index):返回列表中指定位置的元素。

   List<E> subList(int fromIndex,int toIndex):返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。

   ListIterator<E> listIterator():返回此列表元素的列表迭代器(按适当顺序)。

  代码示例:

import java.util.*;
/*
List特有方法:
*/
class ListDemo 
{
	public static void main(String[] args) 
	{
		ArrayList al=new ArrayList();

		//添加元素
		al.add("java01");
		al.add("java02");
		al.add("java03");

		System.out.println("原集合是:"+al);

		//在指定位置添加元素
		al.add(1,"java06");
		System.out.println("角标1处添加java06元素后:"+al);

		//删除之指定位置的元素
		al.remove(2);
		System.out.println("删除角标2元素后:"+al);

		//修改元素
		al.set(2,"java08");
		System.out.println("修改角标2为java08元素后:"+al);

		//通过角标获取元素
		System.out.println("get(1):"+al.get(1));

		System.out.println(al);

		//获取所有元素
		for (int x=0;x<al.size();x++ )
		{
			System.out.println("al("+x+")="+al.get(x));
		}

		for (ListIterator li=al.listIterator();li.hasNext() ; )
		{
			System.out.println("next:"+li.next());
		}
		
	}
}
  程序运行后的结果如下图:



 3.LinkedList

  1)概述

   LinkedList底层使用的是链表数据结构。特点:增删速度很快,查询稍慢。

  2)特有方法

   a)添加元素:

    void addFirst(E e):将指定元素插入此列表的开头。

    void addLast(E e):将指定元素添加到此列表的结尾。

   b)获取元素并删除该元素:

    E removeFirst():移除并返回此列表的第一个元素。返回该列表的第一个元素,但在集合中删除该元素。

    E removeLast():移除并返回此列表的最后一个元素。返回该列表的最后一个元素,但在集合中删除该元素。

   c)获取元素但不删除元素:

    E getFirst():返回此列表的第一个元素。

    E getLast():返回此列表的最后一个元素。

   代码示例:

import java.util.*;
/*
LinkedList集合特有方法:
*/
class LinkedListDemo 
{
	public static void main(String[] args) 
	{
		LinkedList lk=new LinkedList();//创建一个LinkedList集合

		//将指定元素插入列表开头
		lk.addFirst("java01");
		lk.addFirst("java02");
		System.out.println("将指定元素插入列表开头后:"+lk);

		//将指定元素插入列表结尾
		lk.addLast("java03");
		lk.addLast("java04");
		System.out.println("将指定元素插入列表结尾后:"+lk);

		//获取元素但不删除元素
		System.out.println("获取第一个元素:"+lk.getFirst());
		System.out.println("获取最后一个元素:"+lk.getLast());

		//获取元素并删除元素
		System.out.println("获取第一个元素并删除:"+lk.removeFirst());
		System.out.println("删除后集合为:"+lk);
		System.out.println("获取最后一个元素并删除:"+lk.removeLast());
		System.out.println("删除后集合为:"+lk);

	}
}
  程序运行后的结果如下图:


  3)代码练习

import java.util.*;
/*
需求:使用LinkedList集合模拟一个堆栈或者队列数据结构。

堆栈:先进后出。如同一个杯子的水倒进与倒出。
队列:先进先出,如同一个水管中的水的流进与流出。
*/
class  LinkedListTest1
{
	public static void main(String[] args) 
	{
		DuiLie dl=new DuiLie();
		dl.myAdd("java01");
		dl.myAdd("java02");
		dl.myAdd("java03");
		
		while (!dl.myIsEmpty())
		{
			System.out.println(dl.myGet());
		}

	}
}

//队列
class DuiLie
{
	private LinkedList link;
	DuiLie()
	{
		link=new LinkedList();
	}

	public void myAdd(Object obj)
	{
		link.addFirst(obj);
	}

	public Object myGet()
	{
		return link.removeLast();//如果模拟堆栈,只需改为link.removeFirst()即可。
	}

	public boolean myIsEmpty()
	{
		return link.isEmpty();
	}

}
   程序运行后的结果如下图:


 4.Vector

  1)概述

   Vector是1.0版本出现的,Vector类是可以实现可增长的数组对象。Vector 的大小可以根据需要增大或缩小,以适应创建 Vector 后进行添加或移除项的操作。Vector底层是数组数据结构。线程同步,但已被ArrayList替代了。

   用new Vector()创建对象时,会构造一个空向量,使其内部数据数组的大小为 10,如果超过该容量,则会在新创建一个同等大小的数组,将之前的数据移动到新建数组中。

  2)Enumeration(枚举)

   枚举是Vector的特有取出方式,因为枚举的名称及方法名称都过长,且功能和迭代器是一样的,因此已经被迭代器取代了,使用时将优先考虑迭代器。但是枚举在IO中的SequenceInputStream类中有作为参数使用,因此对这一块需稍加了解。

   获取方式:

   a)创建Vector集合对象。

   b)调用elements()方法获得枚举对象。

   示例:

    Vector v=new Vector();//创建Vector集合

    Enumeration e=v.elements();//获取枚举对象

  3)代码练习:

import java.util.*;

class VectorTest
{
	public static void main(String[] args) 
	{
		Vector v=new Vector();//创建Vector集合对象
		
		//添加元素
		v.add("java01");
		v.add("java02");
		v.add("java03");

		Enumeration e=v.elements();//获取枚举对象

		//获取集合的元素并打印
		while (e.hasMoreElements())
		{
			System.out.println(e.nextElement());
		}
	}
}
   程序运行后的结果如下图:


 5.ArrayList

  1)概述

   ArrayList底层的数据结构使用的是数组结构。特点:查询速度很快,但是增删稍慢,且线程不同步。

   用new ArrayList()创建对象时,会构造一个空向量,使其内部数据数组的大小为 10,如果超过该容量,则会再重新创建一个数组,大小为之前的一半并将之前的数据移动到新建数组中。

  2)代码练习

  练习1:去除ArrayList集合中重复元素。

import java.util.*;
/*
练习1:去除ArrayList集合中的重复元素。
*/
class  ArrayListTest1
{
	public static void main(String[] args) 
	{
		ArrayList al=new ArrayList();//创建ArrayList集合
		Iterator i=al.iterator();//获取迭代器对象
		
		//添加元素
		al.add("java01");
		al.add("java02");
		al.add("java05");
		al.add("java02");
		al.add("java01");

		System.out.println(al);//打印原集合
		al=singleElement(al);//去除原集合重复元素
		System.out.println(al);//打印新集合
	}

	//去除ArrayList集合中的重复元素
	public static ArrayList singleElement(ArrayList al)
	{
		ArrayList newAl=new ArrayList();//创建一个新集合
		
		//对原集合进行遍历
		for (Iterator i=al.iterator();i.hasNext() ; )
		{
			Object obj=i.next();
			if (!newAl.contains(obj))
			{
				newAl.add(obj);//将没有包含的元素添加到新集合中
			}
		}
		return newAl;//返回新集合
	}
}
   程序运行后的结果如下图:


  练习2:将自定义对象作为元素存储到ArrayList集合中,并去除重复元素。比如,存人对象,如果人的姓名和年龄都相同,就视为同一个人,即为重复元素。

<pre name="code" class="java">import java.util.*;

class ArrayListTest2 
{
	public static void main(String[] args) 
	{
		ArrayList al=new ArrayList();

		al.add(new Person("zhangsan",20));
		al.add(new Person("zhangsan",20));
		al.add(new Person("lisi",23));
		al.add(new Person("lisi",23));
		al.add(new Person("wangwu",24));
		al.add(new Person("suiqi",25));

		al=singleElement(al);
		
		for (Iterator i=al.iterator();i.hasNext() ; )
		{
			Person p=(Person)i.next();
			System.out.println(p.getName()+"--"+p.getAge());
		}
	}
	public static ArrayList singleElement(ArrayList al)
	{
		ArrayList newAl=new ArrayList();
		for (Iterator i=al.iterator();i.hasNext(); )
		{
			Object obj=i.next();
			
			//contains方法底层自动调用了obj对象的equals方法,并与集合的每个元素进行比较.
			//obj是父类引用,指向了子类Person对象,实际调用的Person的equals方法。
			if (!newAl.contains(obj))
			{
				newAl.add(obj);
			}		
		}
		return newAl;
	}
}

class Person
{
	private String name;
	private int age;
	Person(String name,int age)
	{
		this.name=name;
		this.age=age;
	}

	public String getName()
	{
		return name;
	}

	public int getAge()
	{
		return age;
	}

	//复写Object的equals方法
	public boolean equals(Object obj)
	{
		if (!(obj instanceof Person))
		{
			throw new RuntimeException();
		}
		Person p=(Person)obj;
		return this.name.equals(p.name)&&this.age==p.age;
	}
}

 

  程序的运行结果如下图:

三、set集合

 1.概述

  Set集合元素是无序的,即存入和取出的顺序不一定一致,元素不可以重复。Set集合的功能和Collection是一致的,没有特有方法。Set接口的常见实现子类有HashSet和TreeSet。其架构关系如下:  

  |--Set :元素是无序的(存入和取出的顺序不一定一致),元素不可以重复。

    |--HashSet:底层数据结构是哈希表。

    |--TreeSet:底层数据结构是二叉树。可以对Set集合中的元素进行排序,默认排序方式为自然排序,也成字典排序。

  问题思考:

  1)HashSet如何保证元素的唯一性?

   答:通过元素的两个方法来完成,即HashCode()和equals()。如果元素的hashCode值相同,才会判断equals是否为true。如果元素的hashCode值不同,则不会调用equals方法。

   注:判断元素是否存在,以及删除等操作,依赖的方法也是元素的hashCode和equals方法。

  2)TreeSet如何保证元素的唯一性?

   答:通过compareTo方法的返回值,是正整数、负整数或零,则两个对象较大、较小或相同。相等时则不会存入。

 2.HashSet

  1)概述

   HashSet集合的底层数据结构是哈希表,元素是无序的,且不可以重复。特点:线程不安全,但存取速度快。

  2)哈希表

   哈希表存储的是对象的哈希值,哈希值通过该对象的hashCode方法获得,该方法继承于Object类。如果两个对象的哈希地址值相同,则再通过equals方法比较对象的内容,如果内容不同,则在相同的哈希地址值下顺延,如果内容相同,则视为重复元素,不进行存储。

   代码示例:

import java.util.*;
/*
需求:往HashSet集合存入自定义对象,比如人。如果人的姓名和年龄都相同,则视为同一个人,即为重复元素。

思路:
	自定义hashCode方法,使当人的姓名和年龄都相同的情况下,返回的hashCode值一致。再复写Object的equals方法。
如果hashCode值一致,则会比较自定义的equals方法,使equals比较的内容为姓名和年龄即可,如果都相同则返回true,
否则返回false。
	
*/
class HashSetDemo 
{
	public static void main(String[] args) 
	{
		HashSet hs=new HashSet();

		hs.add(new Person("zhangsan",20));
		hs.add(new Person("zhangsan",20));
		hs.add(new Person("lisi",23));
		hs.add(new Person("wangwu",24));
		hs.add(new Person("wangwu",24));

		for (Iterator i=hs.iterator();i.hasNext() ; )
		{
			Person p=(Person)i.next();
			System.out.println(p.getName()+"---"+p.getAge());
		}

	}
}

class Person
{
	private String name;
	private int age;

	Person(String name,int age)
	{
		this.name=name;
		this.age=age;
	}

	public String getName()
	{
		return name;
	}

	public int getAge()
	{
		return age;
	}
	//复写HashCode方法
	public int hashCode()
	{
		return name.hashCode()+age;
	}

	//复写equals方法
	public boolean equals(Object obj)
	{
		if (!(obj instanceof Person))
		{
			return false;
		}
		Person p=(Person)obj;
		return this.name.equals(p.name)&&this.age==p.age;
	}
}

   程序的运行结果如下图:


  3.TreeSet

  1)概述

   TreeSet的底层数据结构是二叉树。可以对Set集合中的元素进行排序,默认排序方式为自然排序,也称字典排序。

   注:要在TreeSet集合添加元素,该元素对象比较具备比较性,也就是必须要实现Comparable接口,否则将发生ClassCastException异常。

   代码示例:

import java.util.*;
/*
TreeSet集合的自然排序
*/
class TreeSetDemo 
{
	public static void main(String[] args) 
	{
		TreeSet ts=new TreeSet();

		ts.add("abb");
		ts.add("dec");
		ts.add("cde");
		ts.add("bcd");

		for (Iterator i=ts.iterator();i.hasNext() ; )
		{
			Object obj=i.next();
			System.out.println(obj);
		}
	}
}
   程序的运行结果如下图:


  从程序的运行结果可以看出,TreeSet集合的默认排序是按照字母的顺序进行排序的。

  2)Comparable接口(第一种排序方式)

   从上面的示例中看出,TreeSet集合可以对添加的字符串对象元素进行自然排序,其实并不是对所有对象都能实现自然排序,而是需要该对象具备比较性才行,也就是String对象能够进行排序,是因为String对象具备了比较性,而要对象具备比较性就需要实现Comparable接口,复写comparaTo方法。因此String对象能够进行排序的原因就是因为String对象已经实现了Comparable接口,并自定义了自己的排序方式。

   代码练习:往TreeSet集合存入自定义对象人,并按照人的年龄进行排序,如果年龄相同,则按照姓名自然排序。

import java.util.*;
/*
练习1:往TreeSet集合存入自定义对象人,并按照人的年龄进行排序。

思路:
	创建一个Person类,并实现Comparable接口,让Person类具备比较性,并复写compareTo方法,实现
	按照人的年龄进行排序。
*/

class TreeSetTest1 
{
	public static void main(String[] args) 
	{
		TreeSet ts=new TreeSet();

		ts.add(new Person("lisi08",20));
		ts.add(new Person("lisi02",26));
		ts.add(new Person("lisi03",23));
		ts.add(new Person("lisi06",23));
		ts.add(new Person("lisi05",25));

		for (Iterator i=ts.iterator();i.hasNext() ; )
		{
			Person p=(Person)i.next();
			System.out.println(p.getName()+"--"+p.getAge());
		}

	}
}

class Person implements Comparable
{
	private String name;
	private int age;

	Person(String name,int age)
	{
		this.name=name;
		this.age=age;
	}

	public String getName()
	{
		return name;
	}
	
	public int getAge()
	{
		return age;
	}

	//复写compareTo方法
	public int compareTo(Object obj)
	{
		if (!(obj instanceof Person))
		{
			throw new RuntimeException("比较对象不一致");
		}
		Person p=(Person)obj;
		if (this.age>p.age)
		{
			return 1;
		}
		if (this.age==p.age)
		{
			return this.name.compareTo(p.name);
		}
		return -1;
	}
}
   程序运行后的结果如下图:


   注:当进行排序时,如果主要条件相同,一定要判断一下次要条件。

  3)二叉树  

   二叉树示意图:


   图中每个对象里的数字为二叉树结构的元素的取出顺序,存入时每个元素都与第一个存入的元素进行比较,如果小于该元素则往左边放,否则往右边放,依次比较下去。

   练习2:利用二叉树结构的存放取出原理,将TreeSet集合中的元素按照存入顺序取出。

import java.util.*;
/*
练习2;利用二叉树结构的存放取出原理,将TreeSet集合中的元素按照存入顺序取出。

思路:
	复写compareTo方法,使其返回值始终为1,这样便将元素依次存入右边,而取出的时候则从左边开始
	进行取,便可实现按照存入顺序取出。
*/
class TreeSetTest2 
{
	public static void main(String[] args) 
	{
		TreeSet ts=new TreeSet();

		ts.add(new Person("lisi08",20));
		ts.add(new Person("lisi02",26));
		ts.add(new Person("lisi03",23));

		for (Iterator i=ts.iterator();i.hasNext() ; )
		{
			Person p=(Person)i.next();
			System.out.println(p.getName()+"--"+p.getAge());
		}

	}
}

class Person implements Comparable
{
	private String name;
	private int age;

	Person(String name,int age)
	{
		this.name=name;
		this.age=age;
	}

	public String getName()
	{
		return name;
	}
	
	public int getAge()
	{
		return age;
	}

	//复写compareTo方法
	public int compareTo(Object obj)
	{
		return 1;
	}
}
   程序运行后的结果如下图:


  4)Comparator接口(第二种排序方式)

   Comparator是一个比较器,当元素对象自身不具备比较性的时候,可以通过让容器自身具备比较性也是可以实现对TreeSet集合的排序。当两种排序方式都具备时,TreeSet集合会以比较器的方式进行排序。

 实现方式:定义一个比较器,将比较器对象作为参数传入TreeSet集合的构造函数中。

   代码示例:

import java.util.*;
/*
需求:往TreeSet集合存入自定义对象人,用Comparator比较器方式并按照人的年龄进行排序。

思路:
	自定义一个比较器并实现Conparator接口,复写compare方法,使其按照年龄排序,再将自定义
	自定义的比较器对象作为参数传递为TreeSet集合的构造函数。
*/

class ComparatorDemo
{
	public static void main(String[] args) 
	{
		TreeSet ts=new TreeSet(new myComparator());

		ts.add(new Person("lisi08",20));
		ts.add(new Person("lisi02",26));
		ts.add(new Person("lisi03",23));
		ts.add(new Person("lisi06",23));
		ts.add(new Person("lisi05",25));

		for (Iterator i=ts.iterator();i.hasNext() ; )
		{
			Person p=(Person)i.next();
			System.out.println(p.getName()+"--"+p.getAge());
		}

	}
}

class Person 
{
	private String name;
	private int age;

	Person(String name,int age)
	{
		this.name=name;
		this.age=age;
	}

	public String getName()
	{
		return name;
	}
	
	public int getAge()
	{
		return age;
	}
}

//自定义一个比较器
class myComparator implements Comparator
{
	//复写compare方法,使其按照姓名排序
	public int compare(Object o1,Object o2)
	{
		Person p1=(Person)o1;
		Person p2=(Person)o2;
		int num=p1.getName().compareTo(p2.getName());//String类具有比较性
		if (num==0)
		{
			return new Integer(p1.getAge()).compareTo(new Integer(p2.getAge()));//Integer对象具有比较性
		}
		return num;
	}
}
   程序运行后的结果如下图:


  5)代码练习

import java.util.*;
/*
练习3:往TreeSet集合存入字符串元素,并按照长度进行排序。

思路:
	由于字符串对象已经具备比较性,但是比较的方式不是需要的,考虑使用自定义比较器的
	方式来进行排序。自定义一个比较器,复写compare方法,使按照字符串的长度进行排序。
*/

class TreeSetTest3
{
	public static void main(String[] args) 
	{
		TreeSet ts=new TreeSet(new myComparator());

		ts.add("adfd");
		ts.add("adfkfd");
		ts.add("abc");
		ts.add("aaa");
		ts.add("df");

		for (Iterator i=ts.iterator();i.hasNext() ; )
		{
			System.out.println(i.next());
		}

	}
}

//自定义一个比较器
class myComparator implements Comparator
{
	//复写compare方法,字符串长度进行排序
	public int compare(Object o1,Object o2)
	{
		String s1=(String)o1;
		String s2=(String)o2;
		int num=new Integer(s1.length()).compareTo(new Integer(s2.length()));//Integer对象具有比较性
		if (num==0)
		{
			return s1.compareTo(s2);//String类具有比较性
		}
		return num;
	}
}
  程序运行后的结果如下图:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值