集合类
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是如何保证元素唯一性的呢?
答:是通过元素的两个方法,hashCode和equals完成,如果元素的hashcode值相同,才会判断equals是否为true。如果元素的hashcode值不同,不会调用equals
注意:对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法。
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集合特有的迭代器,listIterator是Iterator的子接口。
在迭代时,不可以通过集合对象的方法操作集合中的元素。因为会发生ConcurrentModificationException异常。所以,在迭代器时,只能用迭代器的放过操作元素,可是Iterator方法是有限的y
只能对元素进行判断,取出,删除的操作
如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator,该接口只能通过List集合的listIterator方法获取。
boolean hasPrevious():如果以逆向遍历列表,列表迭代器有多个元素,则返回true。
int nextIndex():返回对next的后续调用所d返回元素的索引。
previous():返回列表中的前一个元素。
int previousIndex():返回对previous的后续调用返回元素的索引。
void remove():从列表中移除由next或previous返回的最后一个元素(可选操作)。
void set(E e):用指定元素替换next或previous返回的最后一个元素(可选操作)。
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内集合要具有比较性。
《《《《————————》》》》
———人生百态,濛濛加油!濛濛努力中。。。。——— 濛濛