黑马程序员——集合Collection:体系详述
------<ahref="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
集合框架概述
集合体系结构图
集合框架内错综复杂的继承关系、以及各种不同的接口和类与其通过语言来描述,不如用图片来进行最为直观的展示。以下所展示的图片是集合框架的最新版本的体现。
接口和类的区分图
继承关系简图
继承关系详图
集合的基本特点
1,集合是存储对象最常用的一种方式2,集合是一种容器,有了集合便可以十分方便地对多个对象进行操作3,集合的长度是可变的,而数组的长度却是固定的4,集合只能存对象,数组可以存基本数据类型5,集合可以存不同类型的对象6,集合中存储的都是对象的引用(地址)
Collection
Collection接口的通用方法
Collection定义了集合框架的共性功能。其下两个主要的子接口有:List(列表),Set(集)。
增加:
add方法的参数类型是Object。以便于接收任意类型对象。add(e);
addAll(collection);
import java.util.ArrayList;class CollectionDemo
{public static void main(String[] args) {//创建一个集合容器。使用Collection接口的子类。ArrayListArrayList al = new ArrayList();//1,添加元素。al.add("java01");//add(Object obj);容器内添加的对象是任意类型的,类型不确定,需要用父类,此处是多态al.add("java02");al.add("java03");al.add("java04");//打印原集合。sop("原集合:"+al);//输出:原集合:[java01, java02, java03, java04]}public static void sop(Object obj){System.out.println(obj);}
}
删除:
remove(e);removeAll(collection);clear();
import java.util.ArrayList;class CollectionDemo
{public static void main(String[] args) {//创建一个集合容器。使用Collection接口的子类。ArrayListArrayList al = new ArrayList();//1,添加元素。al.add("java01");//add(Object obj);容器内添加的对象是任意类型的,类型不确定,需要用父类,此处是多态al.add("java02");al.add("java03");al.add("java04");//打印原集合。sop("原集合:"+al);//输出:原集合:[java01, java02, java03, java04]//2,删除元素。al.remove("java02");//输出:remove后集合:[java01, java03, java04]sop("remove后集合:"+al);al.clear();//清空集合。sop("clear后集合:"+al);//输出:clear后集合:[]}public static void sop(Object obj){System.out.println(obj);}
}
判断:
contains(e);isEmpty();
</pre><pre name="code" class="java">import java.util.ArrayList;class CollectionDemo
{public static void main(String[] args) {//创建一个集合容器。使用Collection接口的子类。ArrayListArrayList al = new ArrayList();//1,添加元素。al.add("java01");//add(Object obj);容器内添加的对象是任意类型的,类型不确定,需要用父类,此处是多态al.add("java02");al.add("java03");al.add("java04");sop("原集合:"+al);//输出:原集合:[java01, java02, java03, java04]//2,删除元素。al.remove("java02");//输出:remove后集合:[java01, java03, java04]sop("remove后集合:"+al);al.clear();//清空集合。sop("clear后集合:"+al);//输出:clear后集合:[]//3,判断元素。sop("java03是否存在:"+al.contains("java03"));//输出:java03是否存在:falsesop("集合是否为空?"+al.isEmpty());//输出:集合是否为空?true(此时集合长度为零)}public static void sop(Object obj){System.out.println(obj);}
}
获取交集:
retainAll();
import java.util.ArrayList;class CollectionDemo
{public static void main(String[] args) {//创建一个集合容器。使用Collection接口的子类。ArrayListArrayList al1 = new ArrayList();//al1添加元素al1.add("java01");al1.add("java02");al1.add("java03");al1.add("java04");ArrayList al2 = new ArrayList();//al2添加元素al2.add("java01");al2.add("java02");al2.add("java08");al2.add("java09");al2.add("java10");//al1.retainAll(al2)al1.retainAll(al2);sop("al1:" + al1);//输出:al1:[java01, java02]sop("al2:" + al2);//输出:al2:[java01, java02, java08, java09, java10]//al2.retainAll(al1)al2.retainAll(al1);sop("al2:" + al2);//输出:al2:[java01, java02]}
取出元素:
目的是要取出元素并操作元素,所以光靠打印出集合是远远不够的。iterator();size();
迭代器接口Iterator
对于集合的元素取出这个动作:用一个函数来描述不够,需要用多个功能来体现,所以就将取出这个动作封装成一个对象来描述。把取出方式定义在集合的内部,这样取出方式就可以直接访问集合内部的元素,那么取出方式就被定义成了内部类。而每一个容器的数据结构不同,所以取出的动作细节也不一样。但是都具有共性内容: 判断和取出。那么就可以将这些共性抽取,这些内部类都符合一个规则(或者说都抽取出来一个规则),该规则就是Iterator。通过一个对外提供的方法:iterator();,来获取集合的取出对象。
迭代的常见操作
boolean hasNext();//有下一个元素,返回真E next();//取出下一个元素void remove();//移除注:在迭代时循环中next调用一次,就要hasNext判断一次。
import java.util.ArrayList;
import java.util.Iterator;class CollectionDemo
{public static void main(String[] args) {//创建一个集合容器。使用Collection接口的子类。ArrayListArrayList al = new ArrayList();//al添加元素al.add("java01");al.add("java02");al.add("java03");al.add("java04");//利用迭代器获取元素的基本方法Iterator it = al.iterator();//获取迭代器,取出集合中的元素//接口型引用只能指向自己的子类对象,而且该对象并不是被new()出来的,是通过al这个ArrayList调用了iterator()方法获取出来的//sop(it.next());//java01//sop(it.next());//java02//sop(it.hasNext());//truewhile(it.hasNext()){//iterator中的hasNext方法,只要集合中还有下一个元素,就返回真sop(it.next());//iterator中的next方法,取出下一个元素,并通过sop打印}/*输出:java01java02java03java04*/}public static void sop(Object obj){System.out.println(obj);}
}
/*
while代码块如果用for来写,格式如下:
for(Iterator it = al.iterator(); it.hasNext() ; )
{System.out.println(it.next());
}
使用for来写,避免了循环结束后it还在内存中
*/
迭代器使用注意事项
1,迭代器在Collcection接口中是通用的,它替代了Vector类中的Enumeration(枚举)。2,迭代器的next方法是自动向下取元素,要避免出现NoSuchElementException。3,迭代器的next方法返回值类型是Object,所以要记得类型转换。
import java.util.ArrayList;
import java.util.Iterator;class CollectionDemo
{public static void main(String[] args) {//创建一个集合容器。使用Collection接口的子类。ArrayListArrayList al = new ArrayList();//al添加元素al.add("java01");al.add("java02");al.add("java03");al.add("java04");//利用迭代器获取元素的基本方法Iterator it = al.iterator();//获取迭代器,取出集合中的元素//接口型引用只能指向自己的子类对象,而且该对象并不是被new()出来的,是通过al这个ArrayList调用了iterator()方法获取出来的//sop(it.next());//java01//sop(it.next());//java02//sop(it.hasNext());//truewhile(it.hasNext()){//iterator中的hasNext方法,只要集合中还有下一个元素,就返回真sop(it.next());//iterator中的next方法,取出下一个元素,并通过sop打印}/*输出:java01java02java03java04*/}public static void sop(Object obj){System.out.println(obj);}
}
/*
while代码块如果用for来写,格式如下:
for(Iterator it = al.iterator(); it.hasNext() ; )
{System.out.println(it.next());
}
使用for来写,避免了循环结束后it还在内存中
*/
List
体系概述
|--List:元素是有序的,元素可以重复。因为该集合体系有索引。|--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。线程不同步。|--LinkedList:底层使用的链表数据结构。特点:增删速度很快,查询稍慢。线程不同步。|--Vector:底层是数组数据结构。线程同步。被ArrayList替代了。因为效率低。|--Set:元素是无序,元素不可以重复。
List特有方法
增加:
add(index,element);addAll(index,Collection);
import java.util.*;
class ListDemo
{public static void sop(Object obj){System.out.println(obj);}public static void main(String[] args) {ArrayList al = new ArrayList();//添加元素al.add("java01");al.add("java02");al.add("java03");sop("原集合是:"+al);//输出:原集合是:[java01, java02, java03]//在指定位置添加元素。al.add(1,"java09");//在脚标为1的位置插入java09这个元素sop("改变后的集合是:"+al);//输出:改变后的集合是:[java01, java09, java02, java03]}
}
删除:
remove(index);
import java.util.*;
class ListDemo
{public static void sop(Object obj){System.out.println(obj);}public static void main(String[] args) {ArrayList al = new ArrayList();//添加元素al.add("java01");al.add("java02");al.add("java03");sop("原集合是:"+al);//输出:原集合是:[java01, java02, java03]//在指定位置添加元素。al.add(1,"java09");sop("改变后的集合是:"+al);//输出:改变后的集合是:[java01, java09, java02, java03]//删除指定位置的元素。al.remove(2);//移除脚标为2的位置的元素sop("remove后的集合是:"+al);//remove后的集合是:[java01, java09, java03]}
}
修改:
set(index,element);
import java.util.*;
class ListDemo
{public static void sop(Object obj){System.out.println(obj);}public static void main(String[] args) {ArrayList al = new ArrayList();//添加元素al.add("java01");al.add("java02");al.add("java03");sop("原集合是:"+al);//输出:原集合是:[java01, java02, java03]//在指定位置添加元素。al.add(1,"java09");sop("改变后的集合是:"+al);//输出:改变后的集合是:[java01, java09, java02, java03]//删除指定位置的元素。al.remove(2);//移除脚标为2的位置的元素sop("remove后的集合是:"+al);//remove后的集合是:[java01, java09, java03]//修改元素。al.set(2,"java007");//在脚标为2的位置,修改原来的元素的值sop("set后的集合是:"+al);//输出:set后的集合是:[java01, java09, java007]}
}
获取:
get(index):subList(from,to);listIterator();int indexOf(obj):获取指定元素的位置。ListIterator listIterator();
import java.util.*;
class ListDemo
{public static void sop(Object obj){System.out.println(obj);}public static void main(String[] args) {ArrayList al = new ArrayList();//添加元素al.add("java01");al.add("java02");al.add("java03");sop("原集合是:"+al);//输出:原集合是:[java01, java02, java03]//添加al.add(1,"java09");sop("改变后的集合是:"+al);//输出:改变后的集合是:[java01, java09, java02, java03]//删除al.remove(2);//移除脚标为2的位置的元素sop("remove后的集合是:"+al);//remove后的集合是:[java01, java09, java03]//修改al.set(2,"java007");//在脚标为2的位置,修改原来的元素的值sop("set后的集合是:"+al);//输出:set后的集合是:[java01, java09, java007]//获取//get(index):位置->元素//如果al.get(1)写在此处,然后再直接打印al,输出的还是[java01, java09, java007],因为仅仅是在查看sop("get(1)获得的元素是:" + al.get(1));//输出:get(1)获得的元素是:java09//获取所有元素。for(int x=0; x<al.size(); x++)//和数组不同,集合所使用的是size{System.out.println("al("+x+")="+al.get(x));}/*al(0)=java01al(1)=java09al(2)=java007*///int indexOf(obj)元素->位置sop("index="+al.indexOf("java09"));//输出:index=1//subList(from,to);List sub = al.subList(1,3);//取脚标为1,2的两个元素,包含头,不包含尾sop("sub="+sub);//输出:sub=[java09, java007]}
}
ListIterator
ListIterator是List集合特有的迭代器,是Iterator的子接口。
在迭代时,不可以通过集合对象的方法操作集合中的元素。因为会发生ConcurrentModificationException异常。所以在迭代器时,只能用迭代器的方法操作元素。
Iterator方法是有限的,只能对元素进行判断,取出,删除的操作。如果想要其他的操作,如添加、修改等,就需要使用其子接口:ListIterrator。该接口只能通过List集合的ListIterator方法获取。
ListIterator的特有方法
add(obj);//增加set(obj);//修改为objhasPrevious();//判断前面有没有元素previous();//取前一个元素
import java.util.*;class ListIteratorDemo{public static void sop(Object obj){System.out.println(obj);}public static void main(String[] args) {//新建一个ArrayList,并添加3个元素ArrayList aL = new ArrayList();aL.add("java01");aL.add("java02");aL.add("java03");sop(aL);/*//在迭代过程中,准备添加或者删除元素。Iterator it = al.iterator();//此时把元素的引用又取到迭代器中去了//操作元素既可以用add,也可以用迭代器,但是不能同时使用,会发生ConcurrentModificationException异常 while(it.hasNext()){Object obj = it.next();if(obj.equals("java02"))//调用Object类的equals方法//al.add("java008");it.remove();//将java02的引用从集合中删除了。使用了Iterator的remove功能,不过移除的仅仅是集合中元素的引用//但是Iterator中没有add功能,要用迭代器来添加元素,考虑用ListIteratorsop("obj="+obj);//输出:obj1=java01 \n obj2=java02 \n obj3=java03,元素的引用移除了,元素还在内存中,并还在被obj使用,java02还能打出 }sop(al);//输出:[java01,java03],移除后al的结果*/ //新建一个ListIterator对象//使用ListIterator的add方法for(ListIterator li = aL.listIterator(); li.hasNext() ; ){Object obj = li.next(); if(obj.equals("java02"))li.add("java009"); }sop(aL);//输出:[java01, java02, java009, java03],在java02这个元素后面插入一个java009的新元素//使用ListIterator的set方法for(ListIterator li = aL.listIterator(); li.hasNext() ;)//如果使用while的方式,则hasnext()直接为flase,因为li还在内存中{Object obj = li.next();if(obj.equals("java02"))li.set("java006");//把java02的位置替换为Java006}sop(aL);//输出:[java01, java006, java009, java03]//使用ListIterator的hasPrevious、previous方法ListIterator li = aL.listIterator();while(li.hasNext()){sop("next::"+li.next());}while(li.hasPrevious()){sop("pres::" + li.previous());/*pres::java03pres::java009pres::java006pres::java01*/}}
}
Enumeration:Vector
因为枚举的名称以及方法的名称都过长,所以被迭代器取代了。
addElement(obj);//添加元素,相当于add(obj);Enumerationelements();//Vector特有取出方式(枚举)hasMoreElements();//相当于Iterator的hasNext()方法nextElements();//相当于Iterator的next()方法
LinkedList特有方法
增加:
addFirst();addLast();
import java.util.*;class LinkedListDemo
{public static void main(String[] args) {LinkedList link = new LinkedList();//addLast方法:尾端插入link.addLast("java01");link.addLast("java02");link.addLast("java03");link.addLast("java04");sop(link);//输出:[java01, java02, java03, java04]//addFirst方法:首端插入link.addFirst("java11");link.addFirst("java22");link.addFirst("java33");link.addFirst("java44");sop(link);//输出:[java44, java33, java22, java11, java01, java02, java03, java04]}public static void sop(Object obj){System.out.println(obj);}
}
获取:
1,获取但不删除
getFirst();getLast();
removeFirst();removeLast();
package collection;import java.util.*;class LinkedListDemo
{public static void main(String[] args) {LinkedList link = new LinkedList();link.add("java01");link.add("java02");link.add("java03");link.add("java04");sop(link);//输出:[java01, java02, java03, java04]//getFisrtsop(link.getFirst());//输出:java01//getLastsop(link.getLast());//输出:java04//removeFirstwhile(!link.isEmpty()){sop(link.removeFirst());/*java01java02java03java04*/}//removeLastwhile(!link.isEmpty()){//仅为演示用,实际过程中,此处link已经是空的,不会输出sop(link.removeLast());}/*java04java03java02java01*/}public static void sop(Object obj){System.out.println(obj);}
}
JDK6更新方法:
offFirst();offLast();
peekFirst();peekLast();
pollFirst();pollLast();
老方法:如果集合中没有元素,会出现NoSuchElementException新方法:如果集合中没有元素,会返回null。
ArrayList应用实例
package collection;import java.util.*;/*
将自定义对象作为元素存到ArrayList集合中,并去除重复元素。
比如:存人对象。同姓名同年龄,视为同一个人。为重复元素。思路:
1,对人描述,将数据封装进人对象。
2,定义容器,将人存入。
3,取出。List集合判断元素是否相同,依据是元素的equals方法。
*/class Person
{private String name;private int age;Person(String name,int age)//构造器{this.name = name;this.age = age;}//开发时使用setter和getterpublic String getName(){return name;}public int getAge(){return age;}//equals方法:判断对象是否相同public boolean equals(Object obj)//此处的equals对象的equals方法(上帝的方法),根据自定义的要求,复写该equals方法//在容器比较元素是否相同,使用的是equals方法,用对象的equals和另一个对象在比较{if(!(obj instanceof Person))return false;Person p = (Person)obj;//向下转型System.out.println(this.name+"....."+p.name);/*程序输出:主动比较者(this)...被比较者(obj)lisi02.....lisi01lisi04.....lisi01lisi04.....lisi02lisi03.....lisi01lisi03.....lisi02lisi03.....lisi04lisi04.....lisi01lisi04.....lisi02lisi04.....lisi04lisi03.....lisi01lisi03.....lisi02lisi03.....lisi04lisi03.....lisi03*/return this.name.equals(p.name) && this.age == p.age;//返回真就说明相同,返回假就说明不同//此处的equals是调用字符串的equals方法}}class ArrayListTest
{public static void sop(Object obj){System.out.println(obj);}public static void main(String[] args) {ArrayList al = new ArrayList();//ArrayList容器不知道元素相同的条件al.add(new Person("lisi01",30));//其实在存的时候存的是al.add(Object obj);,只有Object才能接收任意对象//把Person往里面传的时候,其实是这样:Object obj = new Person("lisi01",30);类型被提升了//使用next时,返回的是Object,Object中没有Person特有的方法,如果还想要再得到Person类中的方法,需要向下转型al.add(new Person("lisi02",32));al.add(new Person("lisi04",35));al.add(new Person("lisi03",33));al.add(new Person("lisi04",35));//sop(al);//使用singleElement(al)方法后,去掉了重复元素al = singleElement(al);sop("remove 03 :"+al.remove(new Person("lisi03",33)));//remove方法底层也是依赖于元素的equals方法。Iterator it = al.iterator();while(it.hasNext()){Person p = (Person)it.next();//next()返回的是已经被提升的类型,需要子类对象特有的方法(此处如getName)时,需要先向下转型/*其实是两句话的简化Object obj = it.next();Person p =(Person)obj; 意思就是把obj变成Person类型,然后赋给p*/sop(p.getName()+"::"+p.getAge());}}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))//contains方法在判断是否存在该元素的时候,其实是在用对象的equals方法在和对象进行比较,看对象与对象是否相同//如果要自定义新的equals规则,需要复写对象的equals方法//1.lisi01先传入到contains的obj中//2.lisi01被添加进newA1这个集合中//3.lisi02被传入到contains的obj中//4.程序跳转到public boolean equals(Object obj),开始进行equals的比较//5.因为第一个对象lisi01并没有其他对象与之比较,所以直接被传入到newAl中,而第二个对象lisi02则需要调用equals方法与第一个传入的对象lisi01进行比较//6.equals在Object类的源码中的语句是:public boolean equals(Object obj) {return (this == obj)},第一次比较时,obj是lisi01,this是lisi02//7.因为newAl.contains(obj)第一次比较时,相当于lisi02.equals(lisi01),因为lisi01是先存在的,用后来的和先来的比较//8.那么lisi01就传入public boolean equals(lisi01)newAl.add(obj);}return newAl;}
}
Set
|--HashSet:底层数据结构是哈希表。线程不同步。 保证元素唯一性的原理:判断元素的hashCode值是否相同。如果相同,还会继续判断元素的equals方法,是否为true。|--TreeSet:可以对Set集合中的元素进行排序。默认按照字母的自然排序。底层数据结构是二叉树。保证元素唯一性的依据:compareTo方法return 0。Set集合的功能和Collection是一致的。
HashSet
底层实现及概念
1,直接打印对象时,调用对象的toString方法,其底层实现是getClass().getName() + '@' + Integer.toHexString(hashCode())2,我们所看到的@后面的值是对象的hashCode,和真实物理地址并不相同
在HashSet中存入自定义对象
package collection;import java.util.*;/*
往hashSet集合中存入自定对象
姓名和年龄相同为同一个人,重复元素。
*/
class HashSetDemo
{public static void sop(Object obj){System.out.println(obj);}public static void main(String[] args) {//创建一个HashSetHashSet hs = new HashSet();//在HashSet中存入元素hs.add(new Person4("a1",11));hs.add(new Person4("a2",12));hs.add(new Person4("a3",13));hs.add(new Person4("a2",12));//重复的元素//sop("a1:"+hs.contains(new Person("a2",12)));//hs.remove(new Person("a4",13));//取出HashSet中的元素Iterator it = hs.iterator();while(it.hasNext()){Person4 p = (Person4)it.next();sop(p.getName()+"::"+p.getAge());}}
}
class Person4
{private String name;private int age;Person4(String name,int age){this.name = name;this.age = age;}//复写Object类的hashCode方法public int hashCode(){System.out.println(this.name+"....?hashCode");return name.hashCode()+age*37;//如果return了固定值,如return 60,那么所有元素hashcode相同,会不断调用equals方法,效率较低//name.hashCode()调用了String复写Object类的hashCode方法//字符串的hashCode的计算公式为:s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]//age乘以一个数是为了防止这样的情况发生:Stringobj1.hashCode() + Stringobj2.age = Stringobj2.hashCode() + Stringobj1.age}//建立Person对象自己的hashCodepublic String getName(){return name;}public int getAge(){return age;}//复写Object类的equals方法public boolean equals(Object obj){if(!(obj instanceof Person4))return false;Person4 p = (Person4)obj;System.out.println(this.name+"...equals?.."+p.name);return this.name.equals(p.name) && this.age == p.age;}}/*
输出结果://System.out.println(this.name+"....?hashCode");a1....?hashCodea2....?hashCodea3....?hashCodea2....?hashCode//System.out.println(this.name+"...equals?.."+p.name);a2...equals?..a2//sop(p.getName()+"::"+p.getAge());a3::13a1::11a2::12
*/
TreeSet
底层实现及概念
与HashSet相比最大的特点:
实现TreeSet排序的两种方式
1,让元素自身具备比较性
元素需要实现Comparable接口,覆盖compareTo方法。也种方式也成为元素的自然顺序,或者叫做默认顺序。
2,让集合自身具备比较性
当元素自身不具备比较性时,或、比较性并非所需。这时就要让集合自身具备比较性。在集合初始化时,就有了比较方式。
TreeSet底层数据结构:红黑树
TreeSet排序1:让元素自身具备比较性
package collection;/*需求:往TreeSet集合中存储自定义对象学生。想按照学生的"年龄"进行排序。*/
import java.util.*;class TreeSetDemo
{public static void main(String[] args) {TreeSet ts = new TreeSet();ts.add(new Student("lisi02",22));ts.add(new Student("lisi007",20));ts.add(new Student("lisi09",19));ts.add(new Student("lisi08",19));//ts.add(new Student("lisi007",20));//如果比完此处的主要条件:年龄之后,不再比较一下次要条件:姓名,那么当年龄相同而姓名不同的人存进来以后,将不会被存入Iterator it = ts.iterator();while(it.hasNext()){Student stu = (Student)it.next();System.out.println(stu.getName()+"..."+stu.getAge());}}
}//告诉TreeSet用哪种方式进行排//TreeSet本身需要进行排序,但是它并不知道以怎样的方式排,如果不让存入的对象具备比较性,会产生ClassCastException//让元素自身具备比较性:1.实现Comparable接口class Student implements Comparable//该接口强制让学生具备比较性。{private String name;private int age;Student(String name,int age){this.name = name;this.age = age;}//让元素自身具备比较性:2.复写compareTo方法public int compareTo(Object obj){//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){return this.name.compareTo(s.name);//比较完主要条件之后再比较次要条件//用compareTo方法之后,当年龄相同时,还会按照姓名的顺序进行排序输出//String类中本身就包含compareTo方法/*按字典顺序比较两个字符串。该比较基于字符串中各个字符的 Unicode 值。按字典顺序将此 String 对象表示的字符序列与参数字符串所表示的字符序列进行比较。如果按字典顺序此 String 对象位于参数字符串之前,则比较结果为一个负整数。如果按字典顺序此 String 对象位于参数字符串之后,则比较结果为一个正整数。如果这两个字符串相等,则结果为 0;compareTo 只在方法 equals(Object) 返回 true 时才返回 0。*/}return -1;}public String getName(){return name;}public int getAge(){return age;}
}
正序和逆序输出的方式
class TreeSetOptDemo
{public static void main(String[] args) {TreeSet ts = new TreeSet();ts.add(new Student2("lisi02",17));ts.add(new Student2("lisi007",20));ts.add(new Student2("lisi09",19));ts.add(new Student2("lisi08",19));ts.add(new Student2("lisi06",19));//如果比完此处的主要条件:年龄之后,不再比较一下次要条件:姓名,那么当年龄相同而姓名不同的人存进来以后,将不会被存入Iterator it = ts.iterator();while(it.hasNext()){Student2 stu = (Student2)it.next();System.out.println(stu.getName()+"..."+stu.getAge());}}
}//告诉TreeSet用哪种方式进行排//TreeSet本身需要进行排序,但是它并不知道以怎样的方式排,如果不让存入的对象具备比较性,会产生ClassCastException//让元素自身具备比较性:1.实现Comparable接口class Student2 implements Comparable//该接口强制让学生具备比较性。{private String name;private int age;Student2(String name,int age){this.name = name;this.age = age;}//让元素自身具备比较性:2.复写compareTo方法public int compareTo(Object obj){return 1;//1代表后存入的对象总是比先存入的对象大,取的时候默认方式是从小到大取出//结果是按照存入的顺序输出/*return1输出结果:lisi02...17lisi007...20lisi09...19lisi08...19lisi06...19return-1输出结果:lisi06...19lisi08...19lisi09...19lisi007...20lisi02...17*/}public String getName(){return name;}public int getAge(){return age;}
}
TreeSet排序2:让集合自身具备比较性
构造一个新的空 TreeSet,它根据指定比较器进行排序。
注意:comparator接口里面需要复写compare方法,comparable接口里面需要复写的是compareTo方法
import java.util.*;//假设原来按照年龄排序的代码已经固定,现在想在不改变原来代码的基础上,重新按照姓名进行排序//原来已经固定的代码部分class Student implements Comparable//该接口强制让学生具备比较性。{private String name;private int age;Student(String name,int age){this.name = name;this.age = age;}public int compareTo(Object obj){ 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){return this.name.compareTo(s.name);}return -1;}public String getName(){return name;}public int getAge(){return age;}}class TreeSetDemo2
{public static void main(String[] args) {/*使用TreeSet默认构造函数,不传入MyCompare时的结果:TreeSet ts = new TreeSet();按照原来年龄的方式排序lisi06...18lisi09...19lisi007...20lisi02...21lisi02...22lisi007...29使用TreeSet超载构造函数,传入MyCompare类时的结果:TreeSet ts = new TreeSet(new MyCompare());按照新的姓名的方式排序lisi007...20lisi007...29lisi02...21lisi02...22lisi06...18lisi09...19*///TreeSet(Comparator<? super E> comparator) 构造一个新的空 TreeSet,它根据指定比较器进行排序。TreeSet ts = new TreeSet(new MyCompare());ts.add(new Student("lisi02",22));ts.add(new Student("lisi02",21));ts.add(new Student("lisi007",20));ts.add(new Student("lisi09",19));ts.add(new Student("lisi06",18));ts.add(new Student("lisi06",18));ts.add(new Student("lisi007",29));//ts.add(new Student("lisi007",20));//ts.add(new Student("lisi01",40));Iterator it = ts.iterator();while(it.hasNext()){Student stu = (Student)it.next();System.out.println(stu.getName()+"..."+stu.getAge());}}
}//TreeSet排序方式二:让集合自身具备比较性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());//此处的compareTo是调用String复写Object类的compareTo方法,该方法会根据比较结果返回值//主要条件相同时再比较次要条件if(num==0){return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));//数字也可以排序,此处调用Integer整数类复写的compareTo方法//把年龄先封装成整数对象再调用Integer的compareTo方法//将new Integer(s1.getAge())和new Integer(s2.getAge())进行比较/*if(s1.getAge()>s2.getAge())return 1;if(s1.getAge()==s2.getAge())return 0;return -1;*/}return num;}}
Map
基本概念
|--Hashtable:底层是哈希表数据结构,不可以存入null键null值。该集合是线程同步的。JDK1.0,效率低。
|--HashMap:底层是哈希表数据结构。允许使用null键null值,该集合是不同步的。JDK1.2,效率高。|--TreeMap:底层是二叉树数据结构。线程不同步。可以用于给Map集合中的键进行排序。
1,该集合存储键值对,一对一对往里存,要保证键的唯一性。2,Set集合的底层就是Map
常用操作方法
put(K key, V value)putAll(Map<? extends K,? extends V> m)
clear()remove(Object key)
containsValue(Object value)containsKey(Object key)isEmpty()
get(Object key)size() //获取长度values() //获取元素的valueentrySet()keySet()
import java.util.*;
class MapDemo
{public static void main(String[] args) {Map<String,String> map = new HashMap<String,String>();//添加元素//Collection中的add方法返回的是boolean,而put方法返回的是该键被存入后原来的值//如果出现添加相同的键时,那么后添加的值会覆盖原有键对应值。//并put方法会返回被覆盖的值。System.out.println("put01:"+map.put("01","zhangsan1"));//输出:put01:nullSystem.out.println("put01:"+map.put("01","wangwu"));//输出:put01:zhangsan1map.put("02","zhangsan2");map.put("03","zhangsan3");//判断元素System.out.println("containsKey:"+map.containsKey("022"));//输出:containsKey:false//删除元素//键-删-值System.out.println("remove:"+map.remove("02"));//输出:remove:zhangsan2//获取元素System.out.println("get023:"+map.get("023")); //输出:get023:nullSystem.out.println("get01:"+map.get("01")); //输出:get01:wangwumap.put("04",null);//把key"04"存为nullSystem.out.println("get04:"+map.get("04"));//输出:get04:null//hashMap集合中null是可以作为键存在的,hashTable不可存null//可以通过get方法的返回值来判断一个键对应的值是否存在。通过返回null来判断。//获取map集合中所有的值。Collection<String> coll = map.values();System.out.println(coll);//输出:[wangwu, zhangsan3, null] 返回的是Map中的值所组成的CollectionSystem.out.println(map);//输出:{01=wangwu, 03=zhangsan3, 04=null}}
}
Map集合的两种取出方式
Map-keySet方式
Set<k> keySet方法具体步骤:
1,将map中所有的键存入到Set集合。因为set具备迭代器,所以可以用迭代方式取出所有的键2,再根据get方法。获取每一个键对应的值。
import java.util.*;
class MapDemo2
{public static void main(String[] args) {Map<String,String> map = new HashMap<String,String>();map.put("02","zhangsan2");map.put("03","zhangsan3");map.put("01","zhangsan1");map.put("04","zhangsan4");//1,先获取map集合的所有键的Set集合,keySet();Set<String> keySet = map.keySet();//此处的String代表Key的类型在这里是字符串类型//2,有了Set集合,就可以获取其迭代器拿到KeyIterator<String> it = keySet.iterator();//Iterator的泛型和Set一致,因为是在操作Set中的元素while(it.hasNext()){String key = it.next();//3,有了Key就可以通过map集合的get方法获取其对应的值。String value = map.get(key);//把get到的key存在名为value的字符串变量中System.out.println("key:"+key+",value:"+value);}/*程序输出:key:01,value:zhangsan1key:02,value:zhangsan2key:03,value:zhangsan3key:04,value:zhangsan4*/}
}
Map-entrySet方式
Set<Map.Entry<k,v>> entrySet 基本思想:将map集合中的映射关系存入到了Set集合中,而这个关系的数据类型就是:Map.Entry
Entry其实就是Map中的一个static内部接口,为什么要定义在内部?
因为只有当有了Map集合,有了键值对,才会有键值的映射关系。关系属于Map集合中的一个内部事物。而且该事物在直接访问Map集合中的元素。
import java.util.*;
class MapDemo2
{public static void main(String[] args) {Map<String,String> map = new HashMap<String,String>();map.put("02","zhangsan2");map.put("03","zhangsan3");map.put("01","zhangsan1");map.put("04","zhangsan4");//1,将Map集合中的映射关系取出。存入到Set集合中。Set<Map.Entry<String,String>> entrySet = map.entrySet();//Map.Entry是一个代表集合中的映射关系的数据类型//Set内"泛型"要返回的是Map.Entry类型,Map.Entry本身又泛型了<k,v>的类型,这里是<String,String>//2,有了Set集合,就可以获取其迭代器拿到映射关系Iterator<Map.Entry<String,String>> it = entrySet.iterator();//Iterator的泛型和Set一致,因为是在操作Set中的元素while(it.hasNext()){Map.Entry<String,String> me = it.next();//3,拿到了映射关系,就可以用其特有的getKey和getValue方法得到值String key = me.getKey();String value = me.getValue();System.out.println("key:"+key+",value:"+value);}/*程序输出:key:01,value:zhangsan1key:02,value:zhangsan2key:03,value:zhangsan3key:04,value:zhangsan4*/}
}/*
Map.Entry 其实Entry也是一个接口,它是Map接口中的一个内部接口。
interface Map
{public static interface Entry{public abstract Object getKey();public abstract Object getValue();}
}class HashMap implements Map
{class Haha implements Map.Entry{public Object getKey(){}//把抽象方法实现public Object getValue(){}}
}
*/
Map一对多映射关系实例
/*
"yureban"Student("01" "zhangsan"); Student("02" "lisi"); "jiuyeban" Student("01" "wangwu"); Student("02" "zhaoliu");
就如同一个学校有多个教室。每一个教室都有名称。
*/
import java.util.*; class MapDemo3
{ public static void main(String[] args) { //学校集合 HashMap<String,HashMap<String,String>> czbk=new HashMap<String,HashMap<String,String>>(); //预热班集合 HashMap<String,String> yureban=new HashMap<String,String>(); //就业班集合 HashMap<String,String> jiuyeban=new HashMap<String,String>(); //学校中班级集合和名称的映射 czbk.put("yureban",yureban); czbk.put("jiuyueban",jiuyeban); //预热班级中学号与姓名的映射 yureban.put("01","zhangsan"); yureban.put("02","lisi"); //就业班级中学号与姓名的映射 jiuyeban.put("01","wangwu"); jiuyeban.put("02","zhouqi"); //直接显示全部学生信息 getAllStudentInfo(czbk); } //定义一个方法获取全部学生信息,包括在哪个班级,叫什么名字,学号多少 public static void getAllStudentInfo(HashMap<String ,HashMap<String,String>> hm) { for (Iterator<String> it=hm.keySet().iterator();it.hasNext() ; )//用keySet取出方式 { String s= it.next();//班级名称 System.out.println(s+":"); HashMap<String,String> stu=hm.get(s);//班级集合 getStudentInfo(stu); } } //获取班级中学生的信息,包括姓名和学号 public static void getStudentInfo(HashMap<String,String> hm) { for (Iterator<String> it=hm.keySet().iterator();it.hasNext() ; ) { String key=it.next();//学号 String value=hm.get(key);//姓名 System.out.println(key+"..."+value); } }
}
/*
程序输出结果:jiuyueban:01...wangwu02...zhouqiyureban:01...zhangsan02...lisi*/
黑马程序员——集合Collection:体系详述相关推荐
- 黑马程序员-----集合框架类(四) 高级for循环、方法的可变参数及静态导入
------- android培训.java培训.期待与您交流! ---------- 黑马程序员-----集合框架类(四) 高级for循环.方法的可变参数及静态导入 1.1 高级for循环(示例1) ...
- 黑马程序员————集合2(day17)
----------------------ASP.Net+Android+IOS开发----------------------期待与您交流! 集合2 l Collections – sort l ...
- 黑马程序员——集合框架
------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 类集是一个动态对象数组,不受对象数组长度的限制. List集合里面的内容允许重复,Set集合不允 ...
- 黑马程序员————集合框架1(day14)
----------------------ASP.Net+Android+IOS开发----------------------期待与您交流! 集合框架1 l 体系概述 l 共性方法 l 迭代 ...
- 黑马程序员——集合框架(二)
----------- android培训.java培训.java学习型技术博客.期待与您交流! ------------ package com.yang.ex; /*------Set:不包含重复 ...
- 黑马程序员-集合(Map)
---------------------- ASP.Net+Android+IOS开发..Net培训.期待与您交流! ---------------------- 区分map集合和collectio ...
- 黑马程序员入学Java知识——精华总结
黑马程序员入学Java知识--精华总结 J2SE部分,Java高新技术部分,7K面试题部分等黑马入学要求的知识点总结! 一.黑马程序员-java概述与基础知识 6 1.何为编程? 6 2.Java语言 ...
- 传智播客.黑马程序员,学C++不再难!
众所周知,C++难.就好像博大精深的汉语比英语难,这是客观事实,我们并不否认. 但,转念想想,英语也不简单吧?从小学开始学,到了大学,挂在四六级上的同学数不胜数.可貌似没 ...
- 黑马程序员——总集篇
-----------android培训.java培训.java学习型技术博客.期待与您交流!------------ 本人编写技术博客的时候只是针对章节的一些比较重要的知识点来编写的: 个人感觉质量 ...
最新文章
- opencv_python使用cv2.imread()读取中文路径,cv2.imwrite()把图片写入中文路径。
- ## **scrapy+kafka+sparkstream爬取京东Iphone12评论储存数据**
- Oracle TNS 不能启动
- 2017.4.24 js 中的iscroll
- Activity管理(三):activity内核管理方案详细讲解
- vfast-全新的开始——荣新的第一天
- [Tips]Torch功能点记录
- 笔记本应用/测试软件大全(个人使用心得)
- MMDetection-运行时
- YbtOJ-染色计划【树链剖分,线段树,tarjan】
- python自动登录校园网_免费自动登录国科大校园网python脚本
- (STL,vector)木块问题
- css-3d旋转相册
- Linux-nmap命令使用
- 2017年Python从入门到实战教程-徐培成-专题视频课程
- 18.Excel vba开发-计算个人所得税
- ultraedit删除重复项_如何去除文本中的重复行?UltraEdit、Excel去重复方法分享
- 背单词的方法:抗遗忘超自然语境记单词01
- 【解救Ros】CLB的Ros小车imu校正,角速度校正,线速度校正过程
- SVG SMIL 动画(基本动画 、变换动画)