黑马程序员——Java之集合框架(一)
2015-03-21 15:03
417 查看
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
特点:集合的长度是可变的,只能存储对象。
数组和集合都是容器有何不同?
数组虽然也可以存储对象,但长度是固定的,数组中可以存储基本类型的数据数据。
元素都必须遵循一条或者多条规则。如有些允许重复而有些则不能重复、有些必须要按照顺序插入而有些则是散列,有些支持排序但是有些则不支持。
实现其接口的子接口区别:
list元素是有序的,元素可以重复,因为该体系集合有索引。
set元素是无序的,元素不可以重复。
Quenu为队列,阻塞式队列和双端队列。
boolean addAll(Collection<? extendsE> c) 将指定集合中的所有元素都添加到此 集合中
boolean remove(Object o): 如果集合中有与o相匹配的对象,则删除对象o
boolean removeAll(Collection<?> c)移除此集合中那些也包含在指定集合中的所有元素
boolean retainAll(Collection<?> c)从当前集合中删除c集合中不包含的元素(取交集)
void clear()清空集合中的所有元素
Iterator iterator() :返回一个迭代器,用来访问集合中的各个元素
boolean contains(Object o) :判断查找集合中是否含有对象o
boolean containsAll(Collection<?> c) 判断此集合是否包含指定集合中的所有元素,
<T> T[] toArray(T[] a):返回一个内含集合所有元素的array。运行期返回的array和参数a的型别相同,需要转换为正确型别。
注意:可以把集合转换成其它任何其它的对象数组。但是不能直接把集合转换成基本数据类型的数组,因为集合必须持有对象。
List集合判断元素是否相同,依据的是元素的equals方法。
List集合中的contains方法和remove方法都会会调用元素本身的equals方法来进行判断。
特有方法:凡是可以操作角标的方法都是该体系特有的方法。
boolean addAll(int index, Collection c): 将集合c的所有元素添加到指定位置index
Object remove(int index) :删除指定位置上的元素
List<E> subList(int fromIndex,inttoIndex)获取部分对象元素
int indexOf(Object o): 返回第一个出现元素o的位置,否则返回-1
int lastIndexOf(Object o) :返回最后一个出现元素o的位置,否则返回-1
在迭代时,不可以通过集合对象的方法操作集合的元素。因为会发生ConcurrentModificationException并发异常。所以在迭代时,只能使用迭代器的操作元素的方法。可是
interator方法时有限的,只能对元素进行判断,去除删除等操作,不能添加元素。如果想要其他操作如添加、修改等就需要使用其子接口listiterator。该接口只能通过list集合的
listiterator方法获取。
基本操作:
void add(Object o): 将对象o添加到当前位置的前面
Object next() 返回列表中的下一个元素。
int nextIndex(): 返回下次调用next方法时将返回的元素的索引
Object previous():返回前一个对象
nt previousIndex(): 返回下次调用previous方法时将返回的元素的索引7
容器中的元素不断增加,容器的大小也会随着增加。在每次向容器中增加元素的同时都会进行容量检查,当快溢出时,就会进行扩容操作。所以如果我们明确所插入元素的多
少,最好指定一个初始容量值,避免过多的进行扩容操作而浪费时间、效率。
在向一个ArrayList对象添加大量元素的程序中,可使用ensureCapacity方法增加capacity。这可以减少增加重分配的数量。
(1)void ensureCapacity(int minCapacity): 将ArrayList对象容量增加minCapacity
(2)void trimToSize(): 整理ArrayList对象容量为列表当前大小。程序可使用这个操作减少ArrayList对象存储空间。
ArrayList三种遍历方式写法:
remove,insert方法在LinkedList的首部或尾部。
由于实现的方式不同,LinkedList不能随机访问,它所有的操作都是要按照双重链表的需要执行。在列表中索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端)。这
样做的好处就是可以通过较低的代价在List中进行插入和删除操作。
void addLast(Object o):将对象o添加到列表的结尾
Object getLast(): 返回列表结尾的元素
Object removeLast():删除并且返回列表结尾的元素
LinkedList(Collection c): 构建一个链接列表,并且添加集合c的所有元素
枚举是vector的特有的取出方式,枚举和迭代其实一样。因为枚举的名字以及方法名过长而别迭代器替换掉了,
ArrayList和Vector的异同点:
三种遍历方式:
栈是一种非常常见的数据结构,它采用典型的先进后出的操作方式完成的。每一个栈都包含一个栈顶,每次出栈是将栈顶的数据取出。
Stack提供5个额外的方法使得Vector得以被当作堆栈使用。
是一个Collection,只不过其行为不同。实现了Set接口的集合有:HashSet、TreeSet、LinkedHashSet、EnumSet。
hashset底层结构是哈希表,如何保证唯一性?
是通过元素的俩个方法,hashcode和equals来完成。
如果元素的hashcode值相同,才会判断equals是否为ture.
如果元素的hashcode值不相同,则不会调用equals。
注意:对于判断元素是否存在,以及删除等操作,依赖的方法时元素的hashcode和equals方法。
运行结果:
从运行结果上可以看出:
当向Set集合插入数据时候,首先比较hashCode编码,如果集合中已有此hashCode,则进而去比较equals方法,若返回true,则两个数据相同,此时不予插入,若返回false,则可以插入,此时数据插入同一个hashCode的“筒”,若集合中没有此hashCode,则可以直接插入,不需要比较equals方法
Comparator 进行排序,具体取决于使用的构造方法。
Comparable接口
在“集合框架”中有两种比较接口:Comparable接口和Comparator接口。像String和Integer等Java内建类实现Comparable接口以提供一定排序方式,但这样只能实现该接口
一次。对于那些没有实现Comparable接口的类、或者自定义的类,您也可以通过Comparator接口来定义您自己的比较方式。
Comparable接口强行对实现它的每个类的对象进行整体排序。此排序被称为该类的自然排序 ,类的 compareTo 方法被称为它的自然比较方法 。实现此接口的对象列表(和数组)可以通过 Collections.sort(和 Arrays.sort )进行自动排序。
问题一:需要重写hashcode和equals方法吗?
如果只拿TreeSet来说,不用重写equals。因为TreeSet里边的对象都要实现Comparable接口并重写compareTo方法,TreeSet判断元素是否相同以及元素的顺序,都是靠这个方法。
以HashSet为代表的就要重写hashcode 和 equals 方法。
代码实现:
比较器对象对象作为参数传递给treeset集合的构造函数。
覆盖方法:
(1)int compare(Object o1, Object o2):
对两个对象o1和o2进行比较,如果o1位于o2的前面,则返回负值。
如果在排序顺序中认为o1和o2是相同的,返回0。
如果o1位于o2的后面,则返回正值。
(2)boolean equals(Object obj): 指示对象obj是否和比较器相等。
该方法覆写Object的equals()方法,检查的是Comparator实现的等同性,不是处于比较状态下的对象。”
定义一个类,类实现comparator接口,覆盖compare方法。
注意:从结果中也可以看出,当两种方式都存在时,以比较器为主。
提供了一个可以快速访问各个元素的有序集合。同时,它也增加了实现的代价,因为哈希表元中的各个元素是通过双重链接式列表链接在一起的。
“为优化HashSet空间的使用,您可以调优初始容量和负载因子。TreeSet不包含调优选项,因为树总是平衡的。”
队列则是双端队列,支持在头、尾两端插入和移除元素,主要包括:ArrayDeque、LinkedBlockingDeque、LinkedList。
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
一 、集合概述
面向对象语言对对象的体现都是以对象的形式,所以为了对多个对象的操作,就对对象进行存储,集合就是存储对象的最常用的一种方式。特点:集合的长度是可变的,只能存储对象。
数组和集合都是容器有何不同?
数组虽然也可以存储对象,但长度是固定的,数组中可以存储基本类型的数据数据。
二、 集合体系结构图
三 、Collection接口
Collection接口是最基本的集合接口,它不提供直接的实现,JavaSDK提供的类都是继承自Collection的“子接口”如List和Set。Collection所代表的是一种规则,它所包含的元素都必须遵循一条或者多条规则。如有些允许重复而有些则不能重复、有些必须要按照顺序插入而有些则是散列,有些支持排序但是有些则不支持。
实现其接口的子接口区别:
list元素是有序的,元素可以重复,因为该体系集合有索引。
set元素是无序的,元素不可以重复。
Quenu为队列,阻塞式队列和双端队列。
基本操作:
(1) 单元素添加、删除操作:
boolean add(Object o):将对象添加给集合boolean addAll(Collection<? extendsE> c) 将指定集合中的所有元素都添加到此 集合中
boolean remove(Object o): 如果集合中有与o相匹配的对象,则删除对象o
boolean removeAll(Collection<?> c)移除此集合中那些也包含在指定集合中的所有元素
boolean retainAll(Collection<?> c)从当前集合中删除c集合中不包含的元素(取交集)
void clear()清空集合中的所有元素
(2) 获取操作
int size() :返回当前集合中元素的数量Iterator iterator() :返回一个迭代器,用来访问集合中的各个元素
(3)判断操作
boolean isEmpty() :判断集合中是否有任何元素boolean contains(Object o) :判断查找集合中是否含有对象o
boolean containsAll(Collection<?> c) 判断此集合是否包含指定集合中的所有元素,
(4) Collection转换为Object数组 :
Object[] toArray() :返回一个内含集合所有元素的array<T> T[] toArray(T[] a):返回一个内含集合所有元素的array。运行期返回的array和参数a的型别相同,需要转换为正确型别。
注意:可以把集合转换成其它任何其它的对象数组。但是不能直接把集合转换成基本数据类型的数组,因为集合必须持有对象。
1、List 接口
List接口为Collection直接接口。List所代表的是有序的Collection,即它用某种特定的插入顺序来维护元素顺序。用户可以对列表中每个元素的插入位置进行精确地控制,同时可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。实现List接口的集合主要有:ArrayList、LinkedList、Vector、Stack。List集合判断元素是否相同,依据的是元素的equals方法。
List集合中的contains方法和remove方法都会会调用元素本身的equals方法来进行判断。
特有方法:凡是可以操作角标的方法都是该体系特有的方法。
(1) 添加和删除
void add(int index, Object element): 在指定位置index上添加元素elementboolean addAll(int index, Collection c): 将集合c的所有元素添加到指定位置index
Object remove(int index) :删除指定位置上的元素
(2)获取
Object get(int index): 返回List中指定位置的元素List<E> subList(int fromIndex,inttoIndex)获取部分对象元素
int indexOf(Object o): 返回第一个出现元素o的位置,否则返回-1
int lastIndexOf(Object o) :返回最后一个出现元素o的位置,否则返回-1
(3)修改
Object set(int index, Object element) :用元素element取代位置index上的元素,并且返回旧的元素(4)遍历集合
list集合特有的迭代器listiterator是Interator的子接口。在迭代时,不可以通过集合对象的方法操作集合的元素。因为会发生ConcurrentModificationException并发异常。所以在迭代时,只能使用迭代器的操作元素的方法。可是
interator方法时有限的,只能对元素进行判断,去除删除等操作,不能添加元素。如果想要其他操作如添加、修改等就需要使用其子接口listiterator。该接口只能通过list集合的
listiterator方法获取。
基本操作:
(1) 添加元素
void add(Object o): 将对象o添加到当前位置的前面(2)修改
void set(Object o): 用对象o替代next或previous方法访问的上一个元素。如果上次调用后列表结构被修改了,那么将抛出IllegalStateException异常。(3) 正向迭代
boolean hasNext()以正向遍历列表时,判断后一个元素是否存在。Object next() 返回列表中的下一个元素。
int nextIndex(): 返回下次调用next方法时将返回的元素的索引
(4)反向迭代
boolean hasPrevious():以逆向遍历列表时判断前一个元素是否存在。Object previous():返回前一个对象
nt previousIndex(): 返回下次调用previous方法时将返回的元素的索引7
(1)Arraylist集合
ArrayList是一个动态数组,也是我们最常用的集合。它允许任何符合规则的元素插入甚至包括null。每一个ArrayList都有一个初始容量(10),该容量代表了数组的大小。随着容器中的元素不断增加,容器的大小也会随着增加。在每次向容器中增加元素的同时都会进行容量检查,当快溢出时,就会进行扩容操作。所以如果我们明确所插入元素的多
少,最好指定一个初始容量值,避免过多的进行扩容操作而浪费时间、效率。
在向一个ArrayList对象添加大量元素的程序中,可使用ensureCapacity方法增加capacity。这可以减少增加重分配的数量。
(1)void ensureCapacity(int minCapacity): 将ArrayList对象容量增加minCapacity
(2)void trimToSize(): 整理ArrayList对象容量为列表当前大小。程序可使用这个操作减少ArrayList对象存储空间。
ArrayList三种遍历方式写法:
public static void method_3(){ ArrayList a= new ArrayList(); a.add( "aaa"); a.add( "bbb"); a.add( "ccc"); a.add( "ddd"); //第一种方式:迭代器 Iterator it=a.iterator(); while(it.hasNext()){//使用完后对象还依然存在; System.err.println(it.next()); } //第二种方式:for循环迭代器 for(Iterator it=a.iterator();it.hasNext();){ //使用完后对象不存在,节省内存; System. err.println(it.next()); } //第三种方式:for普通循环,get获取 for(int x=0;x<a.size();x++){ System. err.println(a.get(x)); } }
练习一:去除ArrayList中的重复元素。 public class ArrayListTest { //去除ArrayList中的重复元素。 public static ArrayList SingElement(ArrayList al){ ArrayList a= new ArrayList(); for(Iterator in=al.iterator();in.hasNext();){ Object ob=in.next(); if(!a.contains(ob)){ a.add(ob); } } return a; } public static void main(String[] args) { // TODO Auto-generated method stub ArrayList al= new ArrayList(); al.add( "1"); al.add( "2"); al.add( "3"); al.add( "1"); al.add( "2"); System. err.println(al); al= SingElement(al); System. err.println(al); } }
练习三;去除ArrayList中的重复对象元素。 public 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 ; } public boolean equals(Object obj){//contains会调用元素的equals方法。 if(!(obj instanceof Person)) return false ; Person p=(Person)obj; //System.err.println(this.name+p.name); return this .name .equals(p.name) &&this.age ==p.age ; } } public class ArrayListTest1 { //判断元素是否相同。 public static ArrayList SingElement(ArrayList al){ //建立一个新容器。 ArrayList all= new ArrayList(); for(Iterator it=al.iterator();it.hasNext();){ Object obj=it.next(); if(!all.contains(obj)){ all.add(obj); } } return all; } public static void main(String[] args) { ArrayList al= new ArrayList(); al.add( new Person("lisi001.." ,30)); al.add( new Person("lisi002.." ,30)); al.add( new Person("lisi003.." ,30)); al.add( new Person("lisi001.." ,30)); al= SingElement(al); Iterator it=al.iterator(); while(it.hasNext()){ Person p=(Person)it.next(); System.err.println(p.getName()+p.getAge()); } } }
(2)Linkedlist集合
同样实现List接口的LinkedList与ArrayList不同,ArrayList是一个动态数组,而LinkedList是一个双向链表。所以它除了有ArrayList的基本操作方法外还额外提供了get,remove,insert方法在LinkedList的首部或尾部。
由于实现的方式不同,LinkedList不能随机访问,它所有的操作都是要按照双重链表的需要执行。在列表中索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端)。这
样做的好处就是可以通过较低的代价在List中进行插入和删除操作。
特有方法:
LinkedList类添加了一些处理列表两端元素的方法。(1)添加元素
void addFirst(Object o): 将对象o添加到列表的开头void addLast(Object o):将对象o添加到列表的结尾
(2) 获取元素
Object getFirst(): 返回列表开头的元素Object getLast(): 返回列表结尾的元素
(3) 删除元素
Object removeFirst(): 删除并且返回列表开头的元素Object removeLast():删除并且返回列表结尾的元素
(4) 构造方法
LinkedList(): 构建一个空的链接列表LinkedList(Collection c): 构建一个链接列表,并且添加集合c的所有元素
<pre name="code" class="java">//模拟堆栈:先进后出。队列:先进先出; class MyLinkedList { private LinkedList ll; public MyLinkedList(){ ll=new LinkedList(); } //添加元素到开头; public void myadd(Object obj){ ll.addFirst(obj); } //先进先出 public Object fifo(){ return ll.removeLast(); } //先进后出 public Object fiao(){ return ll.removeLast(); } //元素是否为空; public boolean isnull(){ return ll.isEmpty(); } } public class Test3 { public static void main(String[] args){ MyLinkedList mll=new MyLinkedList(); mll.myadd("11"); mll.myadd("22"); mll.myadd("33"); mll.myadd("44"); while(!mll.isnull()){ System.out.println(mll.fifo()); } } }
(2) vector枚举
与ArrayList相似,但是Vector是同步的。所以说Vector是线程安全的动态数组。它的操作与ArrayList几乎一样。枚举是vector的特有的取出方式,枚举和迭代其实一样。因为枚举的名字以及方法名过长而别迭代器替换掉了,
ArrayList和Vector的异同点:
三种遍历方式:
<pre name="code" class="java">public class Test3 { public static void main(String[] args){ Vector v=new Vector(); v.add("111"); v.add("222"); v.add("333"); v.add("444"); //第一种方式:随机访问; for(int x=0;x<v.size();x++){ System.out.println(v.get(x)+"...get..."); } //第二种:迭代器。 Iterator it=v.iterator(); while(it.hasNext()){ System.out.println(it.next()+"...迭代器(iterator)..."); } ListIterator li=v.listIterator(); while(li.hasNext()){ System.out.println(li.next()+"...迭代器(listiterator)..."); } //第三种方式:枚举遍历 Enumeration e=v.elements(); while(e.hasMoreElements()){ System.out.println(e.nextElement()+"...elements..."); } //第四种方式:for循环 for(Iterator it1=v.iterator();it1.hasNext();){ System.out.println(it1.next()+"...for循环(iterator)..."); } for(ListIterator li1=v.listIterator();li1.hasNext();){ System.out.println(li1.next()+"...for循环(listiterator)..."); } } }
<pre name="code" class="java">运行结果:
<pre name="code" class="java">111...get... 222...get... 333...get... 444...get... 111...迭代器(iterator)... 222...迭代器(iterator)... 333...迭代器(iterator)... 444...迭代器(iterator)... 111...迭代器(listiterator)... 222...迭代器(listiterator)... 333...迭代器(listiterator)... 444...迭代器(listiterator)... 111...elements... 222...elements... 333...elements... 444...elements... 111...for循环(iterator)... 222...for循环(iterator)... 333...for循环(iterator)... 444...for循环(iterator)... 111...for循环(listiterator)... 222...for循环(listiterator)... 333...for循环(listiterator)...
(4)stack
Stack继承自Vector,实现一个后进先出的堆栈。栈是一种非常常见的数据结构,它采用典型的先进后出的操作方式完成的。每一个栈都包含一个栈顶,每次出栈是将栈顶的数据取出。
Stack提供5个额外的方法使得Vector得以被当作堆栈使用。
操作 | 说明 |
empty() | 测试堆栈是否为空。 |
peek() | 查看堆栈顶部的对象,但不从堆栈中移除它。 |
pop() | 移除堆栈顶部的对象,并作为此函数的值返回该对象。 |
push(E item) | 把项压入堆栈顶部。 |
search(Object o) | 返回对象在堆栈中的位置,以 1 为基数。 |
2、Set接口
Set 接口继承 Collection 接口,而且它不允许集合中存在重复项,每个具体的 Set 实现类依赖添加的对象的 equals()方法来检查独一性。Set接口没有引入新方法,所以Set就是一个Collection,只不过其行为不同。实现了Set接口的集合有:HashSet、TreeSet、LinkedHashSet、EnumSet。
(1)Hashset集合
HashSet堪称查询速度最快的集合,因为其内部是以HashCode来实现的。它内部元素的顺序是由哈希码来决定的,所以它不保证set 的迭代顺序;特别是它不保证该顺序恒久不变。hashset底层结构是哈希表,如何保证唯一性?
是通过元素的俩个方法,hashcode和equals来完成。
如果元素的hashcode值相同,才会判断equals是否为ture.
如果元素的hashcode值不相同,则不会调用equals。
注意:对于判断元素是否存在,以及删除等操作,依赖的方法时元素的hashcode和equals方法。
<pre name="code" class="java">class Person { private String name; private int age; Person(String name,int age){ this.name=name; this.age=age; } public void setName(String name) { this.name=name; } public String getName(){ return name; } public void setAge(int age) { this.age=age; } public int getAge(){ return age; } //重写hashCode方法,可以提高运行效率。 public int hashCode(){ System.out.println(this.name+"...code..."); return name.hashCode()+age*15; } //重写equals方法,保证数据唯一性。 public boolean equals(Object obj){ if(!(obj instanceof Person)) return false; Person p=(Person)obj; System. err.println(this .name +"重复...判断equals..." +p.name ); return this.name.equals(p.name)&&this.age==age; } } class Test3 { public static void main(String[] args){ HashSet hs=new HashSet(); hs.add(new Person("zhangsan",30)); hs.add(new Person("lisi",40)); hs.add(new Person("wangwu",50)); hs.add(new Person("zhangsan",30)); hs.remove("lisi"); for(Iterator it=hs.iterator();it.hasNext();){ Person p=(Person)it.next(); System.out.println("姓名:"+p.getName()+" 年龄:"+p.getAge()); } } }
运行结果:
zhangsan...code... lisi...code... wangwu...code... zhangsan...code... zhangsan重复...判断equals...zhangsan 姓名:wangwu 年龄:50 姓名:lisi 年龄:40 姓名:zhangsan 年龄:30
从运行结果上可以看出:
当向Set集合插入数据时候,首先比较hashCode编码,如果集合中已有此hashCode,则进而去比较equals方法,若返回true,则两个数据相同,此时不予插入,若返回false,则可以插入,此时数据插入同一个hashCode的“筒”,若集合中没有此hashCode,则可以直接插入,不需要比较equals方法
(2)Treeset集合
基于TreeMap,生成一个总是处于排序状态的set,内部以TreeMap来实现。底层数据结构是二叉树。它是使用元素的自然顺序对元素进行排序,或者根据创建Set 时提供的Comparator 进行排序,具体取决于使用的构造方法。
Comparable接口
在“集合框架”中有两种比较接口:Comparable接口和Comparator接口。像String和Integer等Java内建类实现Comparable接口以提供一定排序方式,但这样只能实现该接口
一次。对于那些没有实现Comparable接口的类、或者自定义的类,您也可以通过Comparator接口来定义您自己的比较方式。
Comparable接口强行对实现它的每个类的对象进行整体排序。此排序被称为该类的自然排序 ,类的 compareTo 方法被称为它的自然比较方法 。实现此接口的对象列表(和数组)可以通过 Collections.sort(和 Arrays.sort )进行自动排序。
问题一:需要重写hashcode和equals方法吗?
如果只拿TreeSet来说,不用重写equals。因为TreeSet里边的对象都要实现Comparable接口并重写compareTo方法,TreeSet判断元素是否相同以及元素的顺序,都是靠这个方法。
以HashSet为代表的就要重写hashcode 和 equals 方法。
Treeset排序一:自然排序
让对象自身具备比较性,需要实现comparable接口,覆盖compareto方法。代码实现:
public 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 o) { // TODO Auto-generated method stub if (!(o instanceof Student)) throw new RuntimeException("此对象不是学生" ); Student s=(Student)o; if (this .age >s.age ) return 1; if (this .age ==s.age ){ return this .name .compareTo(s.name); //如果参数字符串等于此字符串,则返回值 0; //如果此字符串按字典顺序小于字符串参数,则返回一个小于 0 的值; //如果此字符串按字典顺序大于字符串参数,则返回一个大于 0 的值。 } return -1;//return new Integer(this.age).compareTo(new Integer(s.age)); } } public class TreesetDemo { public static void main(String[] args) { // TODO Auto-generated method stub4 TreeSet ts= new TreeSet(); ts.add( new Student("lisi001" ,20)); ts.add( new Student("lisi007" ,25)); ts.add( new Student("lisi003" ,19)); ts.add( newStudent("lisi05" ,23)); ts.add( new Student("lisi04" ,23)); for (Iterator it=ts.iterator(); it.hasNext();){ Student s=(Student) it.next(); System. err.println(s.getName()+"...." +s.getAge()); } } }
2) Comparator接口
若一个类不能用于实现java.lang.Comparable,或者具备的比较性不是自己所需要的。这时就需要让集合本身具备比较性,在集合初始化时,就有了比较方式。定义比较器,将比较器对象对象作为参数传递给treeset集合的构造函数。
覆盖方法:
(1)int compare(Object o1, Object o2):
对两个对象o1和o2进行比较,如果o1位于o2的前面,则返回负值。
如果在排序顺序中认为o1和o2是相同的,返回0。
如果o1位于o2的后面,则返回正值。
(2)boolean equals(Object obj): 指示对象obj是否和比较器相等。
该方法覆写Object的equals()方法,检查的是Comparator实现的等同性,不是处于比较状态下的对象。”
Treeset排序二:自定义排序
如何定义比较器?定义一个类,类实现comparator接口,覆盖compare方法。
<pre name="code" class="java">//自然排序 class Student implements Comparable { private String name; private int age; Student(String name,int age){ this.name=name; this.age=age; } public void setName(String name) { this.name=name; } public String getName(){ return name; } public void setAge(int age) { this.age=age; } public int getAge(){ return age; } public int compareTo(Object obj){ if(!(obj instanceof Student)) throw new RuntimeException("不是学生"); Student s=(Student)obj; //第一种写法: if(this.age>s.age) return 1; if(this.age==s.age) return this.name.compareTo(s.name); return -1; //return new Integer(this.age).compareTo(new Integer(s.age)); } } //定义比较器 class Mycomparator implements Comparator<Student> { public int compare(Student s1,Student s2){ int num=new Integer(s1.getName().length()).compareTo(new Integer(s2.getName().length())); if(num==0) return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge())); return num; } } class Test3 { public static void main(String[] args){ TreeSet<Student> ts=new TreeSet<Student>(new Mycomparator()); ts.add(new Student("aa",30)); ts.add(new Student("bbb",50)); ts.add(new Student("aaaaa",40)); ts.add(new Student("dddd",70)); ts.add(new Student("dddd",50)); for(Iterator it=ts.iterator();it.hasNext();){ Student s=(Student)it.next(); System.out.println("姓名:"+s.getName()+" 年龄:"+s.getAge()); } } }
注意:从结果中也可以看出,当两种方式都存在时,以比较器为主。
(3)LinkedHashSet
LinkedHashSet扩展HashSet。如果想跟踪添加给HashSet的元素的顺序,LinkedHashSet实现会有帮助。LinkedHashSet的迭代器按照元素的插入顺序来访问各个元素。它提供了一个可以快速访问各个元素的有序集合。同时,它也增加了实现的代价,因为哈希表元中的各个元素是通过双重链接式列表链接在一起的。
“为优化HashSet空间的使用,您可以调优初始容量和负载因子。TreeSet不包含调优选项,因为树总是平衡的。”
(4)EnumSet
是枚举的专用Set。所有的元素都是枚举类型。3、Quenu
队列,它主要分为两大类,一类是阻塞式队列,队列满了以后再插入元素则会抛出异常,主要包括ArrayBlockQueue、PriorityBlockingQueue、LinkedBlockingQueue。另一种队列则是双端队列,支持在头、尾两端插入和移除元素,主要包括:ArrayDeque、LinkedBlockingDeque、LinkedList。
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
相关文章推荐
- 黑马程序员:JAVA集合框架知识点一
- 黑马程序员--java学习之集合框架
- 黑马程序员_java基础--集合框架(2)
- 黑马程序员 java 基础 毕向东 面向对象 集合框架 Map HashTable HashMap TreeMap
- 黑马程序员-----java基础十五(java之集合框架)
- 黑马程序员--Java面向对象——集合框架总结
- 黑马程序员——Java基础---集合框架
- 黑马程序员---Java基础--14天(集合框架之一)
- 黑马程序员——面向对象的集合框架(java)
- 黑马程序员--Java基础学习(集合框架)第十五天
- 黑马程序员-JAVA基础之集合框架
- 黑马程序员—Java基础—集合框架3
- 黑马程序员------Java基础学习------集合框架
- 黑马程序员————Java基础之集合框架工具类
- 黑马程序员_java_集合框架
- 黑马程序员_Java的集合框架
- 黑马程序员 Java基础之 集合框架(collection)
- 黑马程序员——【Java基础】——集合框架
- 黑马程序员_Java基础_集合框架(一)_14
- 黑马程序员_Java基础_集合框架