集合(上)

 

集合类

1)       为什么出现集合类?

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

2)       数组和集合类同是容器,有何不同?

1:数组是固定长度的;集合可变长度的。

2:数组可以存储基本数据类型,也可以存储引用数据类型;集合只能存储引用数据类型。

3:数组存储的元素必须是同一个数据类型;集合存储的对象可以是不同数据类型。

3)       集合类的特点:

1:对象封装数据,对象多了也需要存储。集合用于存储对象。可以存储不同的对象。

2:对象的个数确定可以使用数组,但是不确定怎么办?可以用集合。因为集合是可变长度的。

4)       为什么会出现这么多的容器?

因为每一个容器对数据的存储方式都有不同。这个存储方式称之为:数据结构

数据结构:就是容器中存储数据的方式。

对于集合容器,有很多种。因为每一个容器的自身特点不同,其实原理在于每个容器的内部数据结构不同。

集合容器在不断向上抽取过程中。出现了集合体系。

在使用一个体系时,原则:参阅顶层内容。建立底层对象。

集合框架的构成及分类(多看多想多思)

--< java.util >--Collection接口:

Collection

    |--List:有序(元素存入集合的顺序和取出的顺序一致),元素都有索引。元素可以重复。

    |--Set:无序(存入和取出顺序有可能不一致),不可以存储重复元素。必须保证元素唯一性。

1,添加:

add(E a) 确保此collection包含指定的元素

 addAll(Collection<? extends E>c)将指定collection中的所有元素都添加到此collection中。

2,删除

clear()将集合中的元素全删除,即清空集合

remove(Object o)从此collection中移除指定元素的单个实例,如果存在的话注意:删除成功,集合的长度会改变。

removeAll(Collection<?>c)移除此collection中那些也包含在指定collection中的所有元素 

3,判断

boolean  isEmpty()如果此collection不包含元素,则返回true

4,获取

boolean contains(obj) :集合中是否包含指定元素 。

boolean containsAll(Collection) :集合中是否包含指定的多个元素。

int size() 返回此collection中的元素数

5,取交集

boolean retainAll(Collection<?>c)仅保留此collection中那些也包含在指定collection的元素。集合和数组一样,里面存的都是地址。

6,获取集合中所有元素:

Iterator iterator()返回在此collection的元素上进行迭代的迭代器

7,将集合变成数组:

toArray()返回包含此collection中所有元素的数组

toArray(T[]a)返回包含此collection中所有元素的数组,返回数组的运行时类型与指定数组的运行时类型相同。

hashCode()返回此collection的哈希码值。

集合和数组一样,里面存的都是地址。

     1.add方法的参数类型是object,以便于接受任意类型对象

     2.集合中存储的都是对象的引用(地址)

--< java.util >--Iterator接口:

迭代器:是一个接口。作用:用于取集合中的元素。

什么是迭代器

其实就是集合的取出元素的方式,就把取出方式定义在集合的内部,这样取出方式就可以直接访问集合内部的元素,那么取出方式就被定义成了内部类,而每一个容器的数据结构不同,所以取出的动作细节也不一样,但是都有共性内容,判断和取出,那么可以将这些共性抽取,那么这个内部类都符合一个规则,该规则是Iterator。

如何获取集合的取出对象呢?

通过一个对外提供的方法terator();

Iterator<E>中有三个方法:

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

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

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

Iterator it = coll.iterator();//获取容器中的迭代器对象,至于这个对象是是什么不重要。这对象肯定符合一个规则Iterator接口。

-----------------------------------------------------------------------------

public static void main(String[] args) {

        Collection coll = new ArrayList();

        coll.add("abc0");

        coll.add("abc1");

        coll.add("abc2");

        //--------------方式1----------------------

        Iterator it = coll.iterator();

        while(it.hasNext()){

            System.out.println(it.next());

        }

        //---------------方式2用此种----------------------

        for(Iterator it = coll.iterator();it.hasNext(); ){

            System.out.println(it.next());

        }

    }

---------------------------------------------------------------

示例:

import java.util.*;
public class collectionDemo {
	public static void main(String[] args) {
		method();
	}
	public static void method_get()
	{
		//创建一个集合容器,使用collection接口的子类。ArrayList
		ArrayList a1=new ArrayList();
		a1.add("java01");
		a1.add("java03");
		/**Iterator it=a1.iterator();//获取迭代器,用于取出集合中的元素
		while(it.hasNext());
		{ 
		    sop(it.next());
		}//写for更优些。it是局部变量,用完就释放。而while中就没释放。
		*/
		for(Iterator it=a1.iterator();it.hasNext();)
		{
			sop(it.next());
		}
	}
	public static void method()
	{
		   //创建一个集合容器,使用collection接口的子类。ArrayList
				ArrayList a1=new ArrayList();
				//1.添加元素
				a1.add("java01");//add(Object obj)
				a1.add("java03");
				ArrayList a2=new ArrayList();
				//1.添加元素
				a2.add("java01");//add(Object obj)
				a2.add("java02");
				a1.retainAll(a2);//取交集,a1中只会保留和a2中相同的元素
				a1.removeAll(a2);//移除与a2中相同的元素。
				sop("a1:"+a1);
				sop("a2:"+a2);
	}
	public static void base_method()
	{ //创建一个集合容器,使用collection接口的子类。ArrayList
		ArrayList a1=new ArrayList();
		//1.添加元素
		a1.add("java01");//add(Object obj)
		a1.add("java02");
		//打印集合
		sop(a1);
		//2.获取个数,集合长度
		sop("size:"+a1.size());
		//3.删除元素
		a1.remove("java02");
		a1.clear();//清空集合
		//打印改变后的集合
		sop(a1);
		//4判断元素
		sop("java03是否存在"+a1.contains("java03"));
		sop("集合是否为空?"+a1.isEmpty());
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}

--< java.util >--List接口:

collection

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

                 | --ArrayList:底层的数据结构使用的是数组结构,特点:查询速度快。但是增删稍慢。线程不同步。50%延长,是 1.2版线程不同步。它默认的长度10元素,超出时,以50%延长                                                                        

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

                 |--Vector:底层是数组数据结构。1.0版,是同步的。被arrayList替代了。长度为10,长度百分百延长,

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

                |----hashSet :底层数据结构是哈希表。线程是非同步的

hashSet是如何保证元素唯一性的呢?

 答:是通过元素的两个方法,hashCodeequals完成,如果元素的hashcode值相同,才会判断equals是否为true。如果元素的hashcode值不同,不会调用equals

注意:对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcodeequals方法。

TreeSet:可以对set集合中的元素进行排序。Set集合的功能和collection是一致的。

list特有方法,凡是可以操作角标的方法都是该体系特有的方法

1,添加:

    add(index,element) :在指定的索引位插入元素。

    addAll(index,collection) :在指定的索引位插入一堆元素。

2,删除:

    remove(index) :删除指定索引位的元素。 返回被删的元素。

3,获取:

    Object get(index) :通过索引获取指定元素。

    int indexOf(obj) :获取指定元素第一次出现的索引位,如果该元素不存在返回-1;

                      所以,通过-1,可以判断一个元素是否存在。

    int lastIndexOf(Object o) :反向索引指定元素的位置。

    List subList(start,end) :获取子列表。

4,修改:

    Object set(index,element) :对指定索引位进行元素的修改。

5,获取所有元素:

    ListIterator listIterator():list集合特有的迭代器。

 

list集合特有的迭代器,listIteratorIterator的子接口。

在迭代时,不可以通过集合对象的方法操作集合中的元素。因为会发生ConcurrentModificationException异常。所以,在迭代器时,只能用迭代器的放过操作元素,可是Iterator方法是有限的y

只能对元素进行判断,取出,删除的操作

如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator该接口只能通过List集合的listIterator方法获取。

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

int nextIndex():返回对next的后续调用所d返回元素的索引。

previous():返回列表中的前一个元素。

int previousIndex():返回对previous的后续调用返回元素的索引。

void remove():从列表中移除由nextprevious返回的最后一个元素(可选操作)。

void set(E e):用指定元素替换nextprevious返回的最后一个元素(可选操作)。

List集合支持对元素的增、删、改、查。

 

List集合因为角标有了自己的获取元素的方式: 遍历。

for(int x=0; x<list.size(); x++){

  sop("get:"+list.get(x));

}

在进行list列表元素迭代的时候,如果想要在迭代过程中,想要对元素进行操作的时候,比如满足条件添加新元素。会发生.ConcurrentModificationException并发修改异常。

导致的原因是:

集合引用和迭代器引用在同时操作元素,通过集合获取到对应的迭代器后,在迭代中,进行集合引用的元素添加,迭代器并不知道,所以会出现异常情况。

如何解决呢?

既然是在迭代中对元素进行操作,找迭代器的方法最为合适.可是Iterator中只有hasNext,next,remove方法.通过查阅的它的子接口,ListIterator,发现该列表迭代器接口具备了对元素的增、删、改、查的动作。

 

ListIterator是List集合特有的迭代器

ListIterator it = list.listIterator;//取代Iterator it = list.iterator;

可变长度数组的原理:

当元素超出数组长度,会产生一个新数组,将原数组的数据复制到新数组中,再将新的元素添加到新数组中。

ArrayList:是按照原数组的50%延长。构造一个初始容量为 10的空列表。

Vector:是按照原数组的100%延长。

 

注意:对于list集合,底层判断元素是否相同,其实用的是元素自身的equals方法完成的。所以建议元素都要复写equals方法,建立元素对象自己的比较相同的条件依据。

List练习:

import java.util.*;
public class listDemo {
	public static void method()
	{
		 ArrayList a1=new ArrayList();
		    //添加元素
		    a1.add("java01");
		    a1.add("java02");
		    sop("原集合是:"+a1);
		    //在指定位置添加元素,相当于插入,
		    a1.add(1, "java09");
		    //删除指定位置元素。按角标删除
		    a1.remove(2);
		    //修改元素。按角标修改
		    a1.set(2, "java007");
		    //通过角标获取元素
		   sop("get(1)"+ a1.get(1));
		    sop(a1);
		    //获取所有元素
		    for(int x=0;x<a1.size();x++)
		    {
		    	System.out.println("a1("+x+")="+a1.get(x));
		    }
		    Iterator it=a1.iterator();
		    while(it.hasNext())
		    {
		      sop("next:"+it.next());	
		    }
		    //通过indexof获取对象的位置
		    sop("index="+a1.indexOf("java02"));
		    List sub=a1.subList(1, 3);
		    sop("sub="+sub);
	}
	public static void main(String[] args) {
                        //演示列表迭代器 
		 ArrayList a1=new ArrayList();
		    //添加元素
		    a1.add("java01");
		    a1.add("java02");
		    sop("原集合是:"+a1);
		    ListIterator li=a1.listIterator();
		    while(li.hasNext())
		    {
		    	Object obj=li.next();
		    	if(obj.equals("java02"))
		    		li.add("java009");//添加
		    	  li.set("java006");//修改
		    }
		    while(li.hasPrevious())//逆向遍历列表,
		    {
		    	sop("pre:"+li.previous());//
		    }
		    sop("hasNext"+li.hasNext());//正向遍历
		    sop("hasPrevious():"+li.hasPrevious());//逆向遍历。
		    sop(a1);
		 /**   //在迭代过程中,准备添加或删除元素
		    Iterator it=a1.iterator();//这个迭代器不能添加
		    while(it.hasNext())
		    {
		     Object obj=it.next();
		     if(obj.equals("java02"))
		    	// a1.add("java003");
		    	 it.remove();//将Java02的引用从集合中删除了。
		        sop("obj="+obj);
		    }
		    */
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}

《《《《————————》》》》

枚举

(此接口的功能与Interator接口的功能是重复的,此外,Interator接口添加了一个可选的移除操作,并使用较短的方法名,新的实现应该优先考虑使用Interator接口而不是Enumeration接口。)

枚举就是Vector特有的取出方式

     取出方式:迭代器,遍历for循环,安角标索引,枚举

发现枚举和迭代器很像,其实枚举和迭代是一样的,因为枚举的名称以及方法的名称都过长,所以被迭代器取代了,枚举郁郁而终了。Enumeration elements()返回此向量的组件的枚举

import java.util.*;
public class VectorDemo {
	public static void main(String[] args) {
	  Vector v=new Vector();
    v.add("java0");
    v.add("java02");
  Enumeration en= v.elements();
  while(en.hasMoreElements())
  {
	  System.out.print(en.nextElement());
  }
}
}

《《《《————————》》》》

LinkedList的特有方法。

addFirst();

addLast();

在jdk1.6以后。

offerFirst();相当于add

offerLast();

getFirst():获取链表中的第一个元素。如果链表为空,抛出NoSuchElementException;

getLast();获取元素但不删除元素如果集合中没有元素,会出现NosuchElementException

在jdk1.6以后。

peekFirst();获取链表中的第一个元素。如果链表为空,返回null。

peekLast();相当于get

removeFirst():获取链表中的第一个元素,但是会删除链表中的第一个元素。如果链表为空,抛出NoSuchElementException

removeLast();获取元素并删除元素,如果集合中没有元素,会出现NosuchElementException

在jdk1.6以后。

pollFirst();//相当于remove

获取链表中的第一个元素,但是会删除链表中的第一个元素。如果链表为空,返回null。

pollLast();获取元素并删除元素,如果集合中没有元素,会返回null

import java.util.*;
public class LinkedListDemo {
	public static void main(String[] args) {
		LinkedList link=new LinkedList();
		link.addFirst("java01");
		link.addFirst("java011");
		link.addFirst("java01111");//头插法
		link.addFirst("java02");
		link.addLast("java0121");//尾插法
		link.addLast("java011211");
		sop(link);
		sop(link.getFirst());//获取头
		sop(link.getLast());//获取尾
		sop("size="+link.size());//获取长度。
		sop(link.removeFirst());
	    while(!link.isEmpty())
	    {
	    	sop(link.removeFirst());//正着取出
	    	sop(link.removeLast());//反着取出
	    }
	}
    public static void sop(Object obj)
    {
    	System.out.print(obj);
    }
}

练习:使用linkedlist模拟一个堆栈或队列数据结构

堆栈:先进后出 ,如同一个杯子

队列:先进先出 first in  first out 。FIFO  如同一个水管

import java.util.*;
public class linklistTest {
	public static void main(String[] args) {
    Duilie dl=new Duilie();
    dl.myAdd("java01");
    dl.myAdd("java02");
	while(!dl.isNull())
	{
    sop(dl.myGet());
	}
	}
    public static void sop(Object obj)
    {
    	System.out.println(obj);
    }
}
class Duilie
{
	private LinkedList link;
	Duilie()
	{
		link=new LinkedList();
	}
	public void myAdd(Object obj)
	{
		link.addFirst(obj);
	}
	public Object myGet()
	{
		 return link.removeLast();
	}
	public boolean isNull()
	{
		return link.isEmpty();
	}
}

Arraylist练习

1、去除ArrayList集合中的重复元素

import java.util.*;
public class ArrayListTest {
	public static void main(String[] args) {
     ArrayList al=new ArrayList();
     al.add("java01");
     al.add("java02");
     al.add("java03");
     al.add("java04");
     al.add("java01");
     al.add("java02");
     /**
      * 在迭代时循环中next只能调用一次,就要hasNext判断一次。
     Iterator it=al.iterator();
     while(it.hasNext())
     {
    	 sop(it.next()+"....."+it.next());
     }
      */
     sop(al);
     al=singleElement(al);
     sop(al);
	}
	public static ArrayList singleElement(ArrayList al)
	{   //定义一个临时容器
		ArrayList newal=new ArrayList();
			Iterator it=al.iterator();
			while(it.hasNext())
			{
				Object obj=it.next();
				if(!newal.contains(obj))
				{
					newal.add(obj);
				}
			}
			return newal;
	}
	public static void sop(Object obj)
	{ 
		System.out.println(obj);
	}
}

2将自定义对象作为元素存到arraylist集合中,并去除重复元素

比如:存人对象,同姓名同年龄视为同一个人,为重复元素

     思路:

     1,对人描述,将数据封装成人对象

     2,定义容器,将人存入

     3,取出

     arraylist用

     list集合判断元素是否相同,依据的是元素equals方法

import java.util.*;
public class arraylistTest2 {
	public static void main(String[] args) {
           ArrayList al=new ArrayList();
           al.add(new Person("lisi01",23));//al.add(object obj);//object obj=new person("lisi01",23);//提高了
            //al.add(new Person("lisi02",34));
          //al.add(new Person("lisi05",34));
          al.add(new Person("lisi03",23));
          al.add(new Person("lisi04",34));
          al=singleElement(al);
          sop("remove 03:"+al.remove(new Person("lisi03",33)));
          Iterator it=al.iterator();
          while(it.hasNext())
         { 
            Person p=(Person)it.next();//向下转型,强转。
	   sop(p.getName()+":::"+p.getAge());
         }
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
public static ArrayList singleElement(ArrayList al)
{         //定义一个临时容器
	ArrayList newal=new ArrayList();
		Iterator it=al.iterator();
		while(it.hasNext())
		{
			Object obj=it.next();
			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 boolean equals(Object obj)
    {  
    	if(!(obj instanceof Person))
    		return false;
    	Person p=(Person)obj;
    	System.out.println(this.name+",,,,,,,,,,,,,,"+p.name);
    	return this.name.equals(p.name)&&this.age==p.age;
    }
    public String getName()
    {
    	return name;
    }
    public int getAge()
    {
    	return age;
    }	
}

--< java.util >--Set接口

Set接口中的方法和Collection中方法一致的。Set接口取出方式只有一种,迭代器

  |--HashSet:底层数据结构是哈希表,线程是不同步的无序,高效;

      HashSet集合保证元素唯一性:通过元素的hashCode方法,和equals方法完成的。

      当元素的hashCode值相同时,才继续判断元素的equals是否为true。

      如果为true,那么视为相同元素,不存。如果为false,那么存储。

      如果hashCode值不同,那么不判断equals,从而提高对象比较的速度。

      |--LinkedHashSet有序,hashset的子类。

  |--TreeSet对Set集合中的元素的进行指定顺序的排序。不同步。TreeSet底层的数据结构就是二叉树。

哈希表的原理:

1,对对象元素中的关键字(对象中的特有数据),进行哈希算法的运算,并得出一个具体的算法值,这个值 称为哈希值

2,哈希值就是这个元素的位置。

3,如果哈希值出现冲突,再次判断这个关键字对应的对象是否相同。如果对象相同,就不存储,因为元素重复。如果对象不同,就存储,在原来对象的哈希值基础 +1顺延。

4,存储哈希值的结构,我们称为哈希表。

5,既然哈希表是根据哈希值存储的,为了提高效率,最好保证对象的关键字是唯一的。

  这样可以尽量少的判断关键字对应的对象是否相同,提高了哈希表的操作效率。

对于ArrayList集合,判断元素是否存在,或者删元素底层依据都是equals方法。

对于HashSet集合,判断元素是否存在,或者删除元素,底层依据的是hashCode方法和equals方法。

TreeSet:

  用于对Set集合进行元素的指定顺序排序,排序需要依据元素自身具备的比较性。

  如果元素不具备比较性,在运行时会发生ClassCastException异常。

  所以需要元素实现Comparable接口,强制让元素具备比较性,复写compareTo方法

  依据compareTo方法的返回值,确定元素在TreeSet数据结构中的位置。

  TreeSet方法保证元素唯一性的方式:就是参考比较方法的结果是否为0,如果return 0,视为两个对象重复,不存。

注意:在进行比较时,如果判断元素不唯一,比如,同姓名,同年龄,才视为同一个人。

  在判断时,需要分主要条件和次要条件,当主要条件相同时,再判断次要条件,按照次要条件排序。

TreeSet集合排序有两种方式,Comparable和Comparator区别:

1:让元素自身具备比较性,需要元素对象实现Comparable接口,覆盖compareTo方法。

2:让集合自身具备比较性,需要定义一个实现了Comparator接口的比较器,并覆盖compare方法,并将该类对象作为实际参数传递给TreeSet集合的构造函数。

第二种方式较为灵活。

Hashset

import java.util.HashSet;
import java.util.*;
class Demo
{
	public int hashCode()
	{
		return 60;
	}
}
public class hashsetDemo {
	public static void main(String[] args) {
		HashSet hs=new HashSet();
		hs.add("java01");
		hs.add("java02");
		Iterator it=hs.iterator();
		while(it.hasNext())
		{
			sop(it.next());
		}
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}

Hashset

练习:往hashset集合中存入自定对象,姓名和年龄相同为同一个人,重复元素。

import java.util.*;
public class HashSetTest {
	public static void main(String[] args) {
		HashSet hs=new HashSet();
		hs.add(new Person1("a1",11));
		hs.add(new Person1("a2",12));
		hs.add(new Person1("a3",13));
		hs.add(new Person1("a2",12));
		hs.add(new Person1("a3",13));
		hs.add(new Person1("a4",14));
		//判断是否存在
		//hs.contains(new Person1("a1",11));//先判断的是hash值。
		//hs.remove(new Person1("a2”,13));//
		Iterator it=hs.iterator();
		while(it.hasNext())
		{
			Person1 p=(Person1)it.next();
			sop(p.getAge()+"::"+p.getName());
		}
	}
   public static void sop(Object obj)
   {
	   System.out.println(obj);
   }
}
class Person1
{   private String name;
    private int age;
    Person1(String name,int age)
    {
    	this.name=name;
    	this.age=age;
    }
    public int hashCode()
    {
    	//return 60;
    	return name.hashCode()+age*39;
    }
    public boolean equals(Object obj)
    {  
    	if(!(obj instanceof Person1))
    		return false;
    	Person1 p=(Person1)obj;
    	System.out.println(this.name+",,,,,,,,,,,,,,"+p.name);
    	return this.name.equals(p.name)&&this.age==p.age;
    }
    public String getName()
    {
    	return name;
    }
    public int getAge()
    {
    	return age;
    }	
}

Set :无序,不可以重复元素。

     |---HashSet :数据结构是哈希表,线程是非同步的

                 保证元素唯一性的原理:判断元素的hashCode值是否相同

                 如果相同,还会继续判断元素的equals方法,是否为true

     |---TreeSet:可以对Set集合中的元素进行排序。

                底层数据结构是二叉树

                保证元素唯一性的依据

                compareTo方法return 0;

        TreeSet排序的第一种方式,让元素自身具备比较性,

        元素需要实现Comparable接口,覆盖compareTo方法。

        这种方式也称为元素的自然顺序,或叫默认顺序。

        TreeSet排序的第二种方式,当元素自身不具备比较性时,或者具备的比较性不是所需要的,这时就需要让集合自身具备比较性。

        在集合初始化时,就有了比较方式。

需求:往Treeset集合中存储自定义对象,学生,想按照学生的年龄进行排序

import java.util.Iterator;
import java.util.TreeSet;
public class TreeSetDemo {
	public static void main(String[] args) {
		TreeSet ts=new TreeSet();
		ts.add(new Student("lisi09",33));
		ts.add(new Student("lisi02",34));
		ts.add(new Student("lisi23",23));
		ts.add(new Student("lisi01",23));
		ts.add(new Student("lisi23",23));
		ts.add(new Student("lisi01",3));
		Iterator it=ts.iterator();
		while(it.hasNext())
		{   Student stu=(Student)it.next();
			System.out.println(stu.getName()+"...."+stu.getAge());
		}
	}
}
class Student implements Comparable //该接口强制让学生具有比较性
{
	private String name;
	private int age;
	Student(String name,int age)
	{
		this.name=name;
		this.age=age;
	}
  public String getName()
  {
	  return name;
  }
  public int getAge()
  {
	  return age;
  }
  public int compareTo(Object obj)
	{    return 1;//输入的字符串的比较正向,变-1反向
		/**if(!(obj instanceof Student))
		   throw new RuntimeException("不是学生对象");
		   Student s=(Student)obj;
		   System.out.println(this.name+"ddddd"+s.name);
		   if(this.age>s.age)
			   return 1;
		   if(this.age==s.age)
		   {
			   return this.name.compareTo(s.name);
		   }
		   return -1;
		   */
	  }
}

comparable接口强行对实现它的每个类的对象进行整体排序。

记住,排序时,当主要条件相同时,一定要判断一下次要条件 。

可以对set集合中的元素进行排序,底层数据结构是二叉树,保证元素唯一性的依据

compareTo方法return 0;

TreeSet排序的第一种方式:让元素自身具备比较性,元素需要实现comparable接口,覆盖compareTo方法, 这种方式也称为元素的自然顺序,或叫默认顺序。

二叉树:

TreeSet的第二种排序方式、

当元素自身不具备比较性时,或具备的比较性不是所需要的,这时就需要让集合自身具备比较性。在集合初始化时,就有了比较方式。

定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。当两种排序都存在时,以比较器为主。定义一个类,实现Comparator接口,覆盖compare方法。

按姓名排序。

import java.util.*;
public class TreesetDemo2 {
	public static void main(String[] args) {
		TreeSet ts=new TreeSet(new Mycompare());
		ts.add(new Student1("lisi09",33));
		ts.add(new Student1("lisi02",34));
		ts.add(new Student1("lisi23",23));
		ts.add(new Student1("lisi01",23));
		ts.add(new Student1("lisi23",23));
		ts.add(new Student1("lisi01",3));
		Iterator it=ts.iterator();
		while(it.hasNext())
		{   Student1 stu=(Student1)it.next();
			System.out.println(stu.getName()+"...."+stu.getAge());
		}
	}
}
class Mycompare implements Comparator
{
	public int compare(Object obj1,Object obj2)
	{
		Student1 s1=(Student1)obj1;
		Student1 s2=(Student1)obj2;
		
		int num= s1.getName().compareTo(s2.getName());
	   if(num==0)
	   {return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
		  /**if(s1.getAge()>s2.getAge())
			  return 1;
		  if(s1.getAge()==s2.getAge())
			  return 0;
		     return -1;
		     */
	   }
	   return num;
	}
}
class Student1 implements Comparable //该接口强制让学生具有比较性
{
	private String name;
	private int age;
	Student1(String name,int age)
	{
		this.name=name;
		this.age=age;
	}
  public String getName()
  {
	  return name;
  }
  public int getAge()
  {
	  return age;
  }
  public int compareTo(Object obj)
	{    //return 1;//输入的字符串的比较正向,变-1反向
		if(!(obj instanceof Student1))
		   throw new RuntimeException("不是学生对象");
		   Student1 s=(Student1)obj;
		   System.out.println(this.name+"ddddd"+s.name);
		   if(this.age>s.age)
			   return 1;
		   if(this.age==s.age)
		   {
			   return this.name.compareTo(s.name);
		   }
		   return -1;
	  }
}

练习:按照字符串长度排序

字符串本身具备比较性,但是它的比较方式不是所需要的,这时就只能使用比较器。

import java.util.*;
public class TreesetTest {
	public static void main(String[] args) {	
    TreeSet ts=new TreeSet(new stringlencomparator());
     ts.add("aa");
     ts.add("cess");
     ts.add("agweg");
     ts.add("s");
     Iterator it=ts.iterator();
     while(it.hasNext())
     {
    	 System.out.println(it.next());
     }
	}
}
class  stringlencomparator implements Comparator
{
	public int compare(Object o1,Object o2)
	{
		String s1=(String)o1;
		String s2=(String)o2;
		/**  if(s1.length()>s2.length())
		   return 1;
	   if(s1.length()==s2.length())
		   return 0;
	   return -1;
	   */
		int num=new Integer(s1.length()).compareTo(new Integer(s2.length()));
		if(num==0)
			return s1.compareTo(s2);
		return num;
	}
	}

泛型

泛型:jdk1.5版本以后出现新特性,用于解决安全问题,是一个类型安全机制

好处:

1,将运行时期出现问题classcastexception,转移到了编译时期,方便于程序员解决问题,让运行事情问题减少,安全。

2,避免了强制转换麻烦

泛型格式:通过<>来定义要操作的引用数据类型

在使用Java提供的对象时,什么时候写泛型呢

通常在集合框架中很常见

只要见到<>就要定义泛型,其实<>就是用来接收类型的。当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。

泛型练习1、

import java.util.*;
public class GenericDemo {
	public static void main(String[] args) {
	ArrayList<String> a1=new ArrayList<String>();
     a1.add("abc01");
     a1.add("adb23");
     Iterator<String> it=a1.iterator();
     while(it.hasNext())
     {
    	 String s=it.next();
    	 System.out.println(s+":"+s.length());
     }
	}
}

泛型练习2

import java.util.*;
public class GenericDemo2 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
     TreeSet<String> ts=new TreeSet<String>(new LenComparator());
     ts.add("aa");
     ts.add("cess");
     ts.add("agweg");
     ts.add("s");
     Iterator<String> it=ts.iterator();
     while(it.hasNext())
     {
    	 String s=it.next();
    	 System.out.println(s);
     }
	}
}
class LenComparator implements Comparator<String>
{
	public int compare(String o2,String o1)
	{
		int num=new Integer(o2.length()).compareTo(new Integer(o1.length()));
		if(num==0)
			return o2.compareTo(o1);//反向,如果正向是则将o1,o2换一换。
		return num;
	}
}

泛型练习3

public class GenericDemo3 {
	public static void main(String[] args) {
	Utils<Worker> u=new Utils<Worker>();
	u.setObject(new Worker());
	Worker w=u.getObject();
		/*Tool t=new Tool();
		t.setObject(new Worker());
		Worker w=(Worker)t.getObject();
		*/
	}
}
class Worker
{
}
class Student3
{
}
//泛型前做法
//什么时候定义泛型类?
//当类中要操作的引用数据类型不确定的时候,早期定义object来完成扩展
//现在定义泛型来完成扩展
class Tool
{  private Object obj;
   public void setObject(Object obj)
   {
	   this.obj=obj;
   }
   public Object getObject()
   {
	   return obj;
   }
}
//泛型类。
class Utils<QQ>
{
   	private QQ q;
   	public void setObject(QQ q)
   	{
   		this.q=q;
   	}
   	public QQ getObject()
   	{
   		return q;
   	}
}
/**
class Tool
{  private worker w;
   public void setWorker(worker w)
   {
	   this.w=w;
   }
   public worker getWorker()
   {
	   return w;
   }
}
*/

《《《《————————》》》》

泛型类定义的泛型,在整个类中有效,如果被方法使用

      那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。

      为了让不同方法可以操作不同类型,而且类型不确定

      那么可以将泛型定义在方法上

     特殊之处:静态方法不可以访问类上定义的泛型,如果静态方法操作的

      引用数据类型不确定,可以将泛型定义在方法上

public class GenericDemo4 {
	public static void main(String[] args) {
	demo<String> d=new demo<String>();
	d.show("haha");
	d.print(4);
	d.print("hehe");
	demo.method("hahahhahha");
/*	demo d1=new demo();
	d1.show("haha");
	d1.show(new Integer(4));*/
       /* Demo<String> d=new Demo<String>();
        d.show("haha");
        d.print("hehe");*/
	}
}
class demo<T>
{
	public  void show(T t)
	{
		System.out.println("show"+t);
		}
	public <Q> void print(Q q)
	{
		 System.out.println("print"+q);
	}
	public static <w> void method(w t)
	{
		System.out.println(t);
	}
}
/*class Demo<T>
{  public void show(T t)
   { 
	 System.out.println("show"+t);
	}
  public void print(T t)
  {
	  System.out.println("print"+t);
  }
}

泛型定义在接口上

public class genericDemo5 {
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
   InterImpl<Integer> i=new InterImpl<Integer>();
		//  InterImpl i=new InterImpl();
      i.show(4);
	}
}
class InterImpl<T> implements Inter<T>//泛型定义在接口上
{
  public void show(T t)
  {
	  System.out.println("show:"+t);
  }
}
/*class InterImpl implements Inter<String>
{public void show(String t)
{
  System.out.println("show:"+t);	
}
}
*/
interface Inter<T>
{
	void show(T t);
}

《《《《————————》》》》

?通配符,也可以理解为占位符

泛型的限定

 ? extends E :可以接受E类型或者E的子类型,上限

 ? super E:可以接受E类型或E的父类型,下限。

import java.util.*;
class generademo6 {
	public static void main(String[] args)
	{
		/* ArrayList<String> a1=new ArrayList<String>();
	     a1.add("abc1");
	     a1.add("abc2");
	     a1.add("abc3");
	     ArrayList<Integer> a11=new ArrayList<Integer>();
	     a11.add(4);//有自动装箱。
	     a11.add(2);
	     a11.add(5);
	     printColl(a1);
	     printColl(a11);*/
			ArrayList<Person> a1=new ArrayList<Person>();
		a1.add(new Person("abc1"));
		a1.add(new Person("abc2"));
		//printColl(a1);
		ArrayList<student11> a11=new ArrayList<student11>();
		a1.add(new student11("abc1"));
		a1.add(new student11("abc2"));
		printColl1(a11);//Arraylist<Person>a1=new Arraylist<Student>();是不允许的。error。两边一致
	}
	public static void printColl1(ArrayList<? extends Person/*泛型限定*/> a1)
	{
		Iterator<? extends Person> it=a1.iterator();
		while(it.hasNext())
		{
			System.out.println(it.next().getName());
		}
	}
 /*public static void printColl(ArrayList<?String>a1) //ArrayList<String>a1=new ArrayList<Integer>();不允许的。
  {
   Iterator<String? > it=a1.iterator();
   while(it.hasNext())
   {
	   System.out.println(it.next());
//	   System.out.println(it.next().length());//这不不能使用具体方法。
   }
}*/
}
class Person
{
   private String name;
  Person(String name)
  {
	  this.name=name;
  }
  public String getName()
  {
	  return name;
  } 
}
class student11 extends Person
{
	student11(String name)
	{
		super(name);
	}
}
class student11 implements Comparable<Person>//<? super e>
{
	public int compareTo(Person s)
	{
		this.getName();
	}
}
class comp implements Comparator<Person>
{
  public int compare(Person s1,Person s2)
  {
	  return s1.getName().compareTo(s2.getName());
  }
}
TreeSet<student11> ts=new TreeSet<student11>(new comp());
ts.add(new student11("abc11"));

《《《《————————————》》》》

泛型限定是用于泛型扩展用的。

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
public class genercidemo8 {
	public static void main(String[] args) {
		TreeSet<student1> ts=new TreeSet<student1>(new comp());
		ts.add(new student1("aa23"));
		ts.add(new student1("sdf213"));
		Iterator<student1> it=ts.iterator();
		while(it.hasNext())
		{
			System.out.println(it.next().getName());
		}
		TreeSet<worker> ts1=new TreeSet<worker>(new comp()); //comp1());
		ts1.add(new worker("aa23ddf"));
		ts1.add(new worker("sdf213dfsd"));
		Iterator<worker> it1=ts1.iterator();
		while(it1.hasNext())
		{
			System.out.println(it1.next().getName());
		}
	}
}
class comp implements Comparator<Person1>
{ 
	public int compare(Person1 p1,Person1 p2)
	{
		return p2.getName().compareTo(p1.getName());
	}
}
/*
class comp implements Comparator<student1>
{
	public int compare(student1 s1,student1 s2)
	{
		return s1.getName().compareTo(s2.getName());
	}
}
class comp1 implements Comparator<worker>
{
	public int compare(worker s1,worker s2)
	{
		return s1.getName().compareTo(s2.getName());
	}
}
*/
class Person1
{
   private String name;
  Person1(String name)
  {
	  this.name=name;
  }
  public String getName()
  {
	  return name;
  }
}
class student1 extends Person1
{
	student1(String name)
	{
		super(name);
	}
}
class worker extends Person1
{
 	worker(String name)
 	{
 		super(name);
 	}
}

《《《《————————————》》》》

ClassCastException类型转换异常

Comparable 接口强行对实现它的每个类的对象进行整体排序,这种排序被称为自然排序。

Comparable只有comparableTo()

TreeSet内集合要具有比较性。

《《《《————————》》》》

———人生百态,濛濛加油!濛濛努力中。。。。———  濛濛

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值