java中的集合框架
框架:类库的集合。
集合框架:用来表示和操作的统一的架构,包含了实现集合的接口与类。
集合又称为容器(containers),简单的来说集合框架就是一个对象,可以将具有相同性质的多个元素汇聚成一个整体。集合被用于存储、获取操纵和传输聚合的数据----存放数据的容器。
集合框架的核心接口为Collection、 List、 Set 和 Map.

1. Collection集合接口
Collection是一组各自独立的元素,通常拥有相同的套用规则。Set 、List由它派生。
基本操作:
| 方法 | 方法作用 | 
| boolean add(Object obj) | 将指定对象obj新增至集合内,增加成功传回true,否则传回false | 
| boolean addAll(Collection c) | 将指定集合c内所有元素新增至集合内,增加成功传回true,否则传回false | 
| viod clear() | 将集合内所有元素清空 | 
| boolean isEmpty() | 检查集合内是否没有任何元素,如果是传回true,否则传回false | 
| Iterator iterator() | 将集合内的元素信息转存成Iterator对象 | 
| boolean remove(Object obj) | 将指定元素obj从集合内移除,成功移除传回true,否则传回false | 
| int size() | 将集合内的元素总数传回 | 
| Object[] toArray() | 将集合内的元素转存到数组后传回该数组 | 
containsAll()方法:查找当前集合是否包含了另外一个集合的所有元素,即另外一个元素是否是当前集合的子集。
addAll()方法:将另外一个集合中的所有元素添加到当前集合中,类似于“并”操作。
clear()方法:删除当前集合中的所有元素。
removeAll()方法:类似于clear()方法,但是删除的是集合的一个子集。
retainAll()方法:类似于removeAll()方法,从当前集合中删除不属于子集的元素,即“交集运算”。
Iterator接口方法:
| 方法 | 方法说明 | 
| void add(Object obj) | 将Obj插入列表中的一个元素前,该元素在下一次调用next()方法时被返回 | 
| boolean hasNext() | 如果存在下一个元素,则返回true,否则返回false | 
| boolean hasPrevious() | 如果存在前一个元素,则返回true,否则返回false | 
| Object next() | 返回下一个元素,如不存在,引发一个NoSuchElementException异常 | 
| int nextIndex() | 返回下一个元素的下表,如果不存在下一个元素,则返回列表的大小 | 
| Object previous() | 返回前一个元素,如不存在,引发一个NoSuchElementException异常 | 
| void remove() | 从列表中删除当前元素 | 
| void set(Object obj) | 将obj赋给当前元素。即上一次调用next()方法或previousfangfa后返回的元素 | 
Collection实现类:
| 类名 | 类的说明 | 
| AbstractCollection | 实现大多数Collection接口 | 
| AbstractList | 扩展AbstractCollection并实现大多数List接口 | 
| AbstractSequentialList | 为了被类集使用而扩展AbstractList,该类集是连续而不是用随机方式访问其元素 | 
| LinkedList | 通过扩展AbstractSequentialList来实现连接表 | 
| ArrayList | 通过扩展AbstractList来实现动态数组 | 
| AbstractSet | 扩展AbstractCollection并实现大多数AbstractSet | 
| HashSet | 为了使用散列表而扩展AbstractSet | 
| TreeSet | 实现存储在树中的一个集合,扩展扩展AbstractSet | 
所有通用的 Collection 实现类(通常通过它的一个子接口间接实现 Collection)应该提供两个“标准”构造方法:一个是 void(无参数)构造方法,用于创建空 collection;另一个是带有 Collection 类型单参数的构造方法,用于创建一个具有与其参数相同元素新的 collection。实际上,后者允许用户复制任何 collection,以生成所需实现类型的一个等效 collection。尽管无法强制执行此约定(因为接口不能包含构造方法),但是 Java 平台库中所有通用的 Collection 实现都遵从它。
1 package demo; 2 3 import java.util.*; 4 5 /** 6 * 集合框架的简单测试 7 * Created by luts on 2015/12/5. 8 */ 9 public class test { 10 public static void main(String[] args) throws Exception{ 11 Collection country = new HashSet(); //set是无序的、没有重复元素的集合 12 country.add("China"); 13 country.add("Canada"); 14 country.add("Italy"); 15 country.add("Japan"); 16 country.add("China"); //重复插入一个元素 17 18 System.out.println("size = " + country.size()); 19 for (Iterator it = country.iterator(); it.hasNext();) 20 System.out.println(it.next()); 21 22 System.out.println(); 23 24 Collection countryNew = new ArrayList(); //List元素有序,可以添加重复的元素 25 countryNew.add("China"); 26 countryNew.add("Canada"); 27 countryNew.add("Italy"); 28 countryNew.add("Japan"); 29 countryNew.add("China"); //重复插入一个元素 30 System.out.println("size = " + countryNew.size()); 31 for (Iterator it = countryNew.iterator(); it.hasNext();) 32 System.out.println(it.next()); 33 } 34 }
结果:
size = 4 Canada China Japan Italy size = 5 China Canada Italy Japan China
Java集合类collections
就像有专门的java.util.Arrays来处理数组,Java中对集合也有java.util.Collections来处理。
第一组方法主要返回集合的各种数据:
Collections.checkedCollection / checkedList / checkedMap / checkedSet / checkedSortedMap / checkedSortedSet:  
检查要添加的元素的类型并返回结果。任何尝试添加非法类型的变量都会抛出一个ClassCastException异常。这个功能可以防止在运行的时候出错。
Collections.emptyList / emptyMap / emptySet :返回一个固定的空集合,不能添加任何元素。
Collections.singleton / singletonList / singletonMap:返回一个只有一个入口的 set/list/map 集合。
Collections.synchronizedCollection / synchronizedList / synchronizedMap / synchronizedSet / synchronizedSortedMap / synchronizedSortedSet:获得集合的线程安全版本(多线程操作时开销低但不高效,而且不支持类似put或update这样的复合操作)
Collections.unmodifiableCollection / unmodifiableList / unmodifiableMap / unmodifiableSet / unmodifiableSortedMap / unmodifiableSortedSet:返回一个不可变的集合。当一个不可变对象中包含集合的时候,可以使用此方法。
第二组方法中,其中有一些方法因为某些原因没有加入到集合中:
 
Collections.addAll:  添加一些元素或者一个数组的内容到集合中。
Collections.binarySearch:  和数组的Arrays.binarySearch功能相同。
Collections.disjoint:  检查两个集合是不是没有相同的元素。
Collections.fill:  用一个指定的值代替集合中的所有元素。
Collections.frequency:  集合中有多少元素是和给定元素相同的。
Collections.indexOfSubList / lastIndexOfSubList:和String.indexOf(String) / lastIndexOf(String)方法类似——找出给定的List中第一个出现或者最后一个出现的子表。
Collections.max / min:  找出基于自然顺序或者比较器排序的集合中,最大的或者最小的元素。
Collections.replaceAll:  将集合中的某一元素替换成另一个元素。
Collections.reverse:  颠倒排列元素在集合中的顺序。如果你要在排序之后使用这个方法的话,在列表排序时,最好使用Collections.reverseOrder    比较器。
Collections.rotate:根据给定的距离旋转元素。
Collections.shuffle:随机排放List集合中的节点,可以给定你自己的生成器——例如 :java.util.Random / java.util.ThreadLocalRandom or java.security.SecureRandom。
Collections.sort:将集合按照自然顺序或者给定的顺序排序。
Collections.swap:交换集合中两个元素的位置(多数开发者都是自己实现这个操作的)。
2. Set接口
  Set类似于数学中的集合的概念,是无序的、没有重复元素的集合。也就是说Set的构造函数有一个约束条件:传入的Collection参数不能包含重复的元素。常用具体实现有HashSet和TreeSet类。
Set方法:
  
2.1 HashSet类
HashSet类是对AbstractSet类的扩展。它创建了一个类集。该类集使用散列表进行存储,而散列表则通过使用称之为散列法的机制来存储信息。在散列中,一个关键字的信息内容被用来确定唯一的一个值,称为散列码。而散列码则被用来当作与关键字相连的数据的存储下标。
HashSet类的构造方法:

填充比必须介于0.0与1.0之间。它决定在散列集合向上调整大小之前,有多少能被充满。具体地说,就是当元素的个数大于散列集合容量乘以它的填充比时,散列集合会被扩大。
  注意:散列集合并不能确定其元素的排列顺序。
HashSet类的主要方法:
| 方法 | 功能描述 | 
| public boolean add(Object o) | 向集合添加指定元素 | 
| public void clear() | 清空集合中所有元素 | 
| public boolean contains(Object o) | 判断集合是否包含指定元素 | 
| public boolean isEmpty() | 判断集合是否还有元素。如果集合不包含任何元素,则返回true | 
| public Iterator iterator() | 返回对此集合中元素进行迭代的迭代器 | 
| public boolean remove(Object o) | 删除集合中的元素 | 
| public int size() | 返回此集合中的元素的个数 | 
| public Object[] toArray | 将集合中的元素放到数组中,并返回该数组 | 
Set.contains(E e)的时候,先调用从Object继承而来的hashCode方法,然后在调用equals()方法,连个方法都返回真的时候,才认定Set包含某个元素。jvm运行时,给每个对象分配唯一一个标志身份的标志hanshcode。Object的hashCode()方法在默认情况下,判断哈希码是不是相同.即如同equals默认情况下比较的是二者是不是同一个内存快。Set集的contains方法,内部就是先调用hashCode再调用equals()方法。很多情况要结合实际对hashCode、equals方法进行改写.
2.2 TreeSet类
TreeSet为使用树来进行存储的Set接口提供了一个工具。对象按升序进行存储,这方便我们对其进行访问和检索。在存储了大量的需要进行快速检索的排序信息的情况下,TreeSet是一个很好的选择。
TreeSet类的构造方法:

TreeSet类中有几个特殊的方法:
| 方法 | 功能描述 | 
| public E first() | 返回有序集合中第一个元素,即最小的那个元素 | 
| public E last() | 返回有序集合中最后一个元素,即最大的那个元素 | 
| public SortedSet subSet(E fromElement,E toElement) | 返回有序集合从fromElement(包括)到toElement(不包括)的元素 | 
3. List 列表
List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。能够使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于Java的数组。和Set不同,List允许有相同的元素。
3.1 ArrayList

| 方法 | 功能描述 | 
| public boolean add(E o) | 将指定的元素追加到列表的最后 | 
| public void add(int index,E element) | 将参数element表示的元素插入此列表中参数index表示指定位置中 | 
| public boolean addAll(Collection c) | 将Collection中所有元素追加到此列表的尾部 | 
| public void clear() | 删除列表中的所有元素 | 
| public boolean contains(Object elem) | 判断此列表是否包含参数elem表示的指定元素 | 
| public get(int index) | 返回列表中指定位置上的元素 | 
| public boolean isEmpty() | 判断此列表中有没有元素 | 
| public remove(int index) | 删除列表中指定位置上的元素 | 
| public set(int index, E element) | 用参数element表示指定的元素代替列表中指定位置上的元素。 | 
| public int size() | 返回列表中的元素数 | 
| public Object[] toArray() | 返回一个包含列表中所有元素的数组 | 
| public T[] toArray(T[] a) | 返回一个包含列表中所有元素的数组 | 
| void trimToSize() | 将容量调整为该列表的当前大小 | 
3.2 LinkedList类
LinkedList类有两种构造方法:

除了它继承的方法之外,LinkedList类本身还定义了一些有用的方法:

3.3 Vector类
Vector类实现动态数组,这与ArrayList相似,但两者不同的是:Vector类是同步的,并且它包含了一些不属于类集框架的方法。
Vector类的构造方法:

注意:由Vector创建的Iterator,虽然和ArrayList创建的Iterator是同一接口,但是,因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了Vector的状态(例如,添加或删除了一些元素),这时调用Iterator的方法时将抛出ConcurrentModificationException,因此必须捕获该异常。
Vetor提供了用于增加元素的方法:
| 方法 | 方法描述 | 
| public void addElement( Object obj ) | 将指定的组件添加到该向量的末尾,并将其大小增加1 | 
| public void addElement( int index,Object obj ) | 在向量的指定位置插入指定的元素obj,该位置及以后的元素位置后移 | 
| public void insertElementAt( Object obj,int index ) | 将指定对象作为此向量中的组件插入到指定的index处 | 
3.4 Stack类
Stack是Vector的一个子类,它实现标准的后进先出堆栈。Stack仅仅定义了创建空堆栈的默认构造方法。

Stack类包括了Vector类定义的所有方法,同时增加了几种它自己定的方法:
| 方法 | 功能描述 | 
| public E push(Object item) | 将元素引用压入栈顶 | 
| public E pop() | 删除栈顶元素。栈为空则会抛出EmptyStackException异常 | 
| public E peek() | 取得栈顶元素但不删除它。如果栈为空则会抛出EmptyStackException异常 | 
| public boolean empty() | 判断堆栈是否为空 | 
| public int search(Object o) | 返回Object对象在栈中所处的位置。其中栈顶元素位置为1,以后依次递增1。如果对象不在栈中则返回-1 | 
4. Map
Map没有继承Collection接口,映射(map)是一个存储关键字和值的关联,或者说是“关键字/值”对的对象,即给定一个关键字,可以得到它的值。关键字和值都是对象,关键字必须是唯一的,但值是可以被复制的。
映射接口定义了映射的特性和本质。支持映射的三大接口:

Map接口映射唯一关键字到值。关键字是以后用于检索值的对象。给定一个关键字和一个值,可以存储这个值到一个Map对象中。当这个值被存储以后,就可以使用它的关键字来检索它。Map.Entry接口使得可以操作映射的输入。而SortMap接口扩展了Map,它确保了各项关键字按升序排列。
Java转实现映射接口的类:
| 类名 | 类的描述 | 
| AbstractMap | 实现大多数的Map接口 | 
| HashMap | 将AbstractMap扩展到使用散列表 | 
| TreeMap | 将AbstractMap扩展到使用树 | 
4.1 Hashtable类
Hashtable继承Map接口,实现一个key-value映射的哈希表。任何非空(non-null)的对象都可作为key或者value。它与HashMap相似,但Hashtable是同步的。使用Hashtable时,指定一个对象作为关键字,同时指定与该关键字相关联的值。接着该关键字被散列,把得到的散列值作为存储在表中的值的下标。
Hashtable的构造方法:

  添加数据使用put(key, value),取出数据使用get(key),这两个基本操作的时间开销为常数。
 
  Hashtable通过initial capacity和load factor两个参数调整性能。通常缺省的load factor 0.75较好地实现了时间和空间的均衡。增大load factor可以节省空间但相应的查找时间将增大。
4.2 HashMap类
HashMap类使用散列表实现Map接口。HashMap是非同步的,并且允许null,即null value和null key。但是将HashMap视为Collection时(values()方法可返回Collection),其迭代子操作时间开销和HashMap的容量成比例。因此,如果迭代操作的性能相当重要的话,不要将HashMap的初始化容量设得过高,或者load factor过低。
HashMap类的构造方法:

HashMap类的主要方法:
| 方法 | 方法说明 | 
| public void clear() | 删除映射中所有映射关系 | 
| public boolean containsKey(Object key) | 判断HashMap中是否包指定的键的映射关系,如果包含则返回true | 
| public boolean containsValue(Object value) | 判断HashMap中是否包指定的键值的映射关系 | 
| public V get(Object key) | 返回参数key键在该映射中所映射的值 | 
| public boolean isEmpty() | 判断HashMap中是否包含键-值映射关系,如果不包含则返回true | 
| public V put(K key, V value) | 在映射中放入指定值与指定键 | 
| public void putAll(Map m) | 将指定映射的所有映射关系复制到此映射中 | 
| public int size() | 返回映射中键-值映射关系的数目 | 
| public V remove(Object key) | 删除映射中存在该键的映射关系 | 
4.3 TreeMap类

| 方法 | 方法说明 | 
| clear() | 从此TreeMap中删除所有映射关系 | 
| clone() | 返回TreeMap实例的浅表复制 | 
| comparator() | 返回用于对此映射进行排序的比较器,如果此映射使用它的键的自然顺序,则返回null | 
| containsKey(Objectkey) | 如果此映射包含对于指定的键的映射关系,则返回true | 
| containsValue(Objectvalue) | 如果此映射把一个或多个键映射到指定值,则返回true | 
| entrySet() | 返回此映射所包含的映射关系的set视图 | 
| firstKey() | 返回有序映射中当前第一个键 | 
| get(Objectkey) | 返回此映射中映射到指定键的值 | 
| headMap(KtoKey) | 返回此映射的部分视图,其键严格小于toKey | 
| keySet() | 返回此映射中所包含的键的Set视图 | 
| lastKey() | 返回有序映射中当前最后一个键 | 
来自慕课网的例子:Course课程类:
1 /** 2 * Created by Luts on 2015/12/5. 3 */ 4 public class Course { 5 private String id; 6 private String name; 7 public Course(String id, String name){ 8 this.id = id; 9 this.name = name; 10 } 11 12 public Course(){} 13 14 public String getId() { 15 return id; 16 } 17 18 public void setId(String id) { 19 this.id = id; 20 } 21 22 public String getName() { 23 return name; 24 } 25 26 public void setName(String name) { 27 this.name = name; 28 } 29 }
学生类:
1 import java.util.*; 2 3 /** 4 * Created by Luts on 2015/12/5. 5 */ 6 public class Student { 7 private String id; 8 private String name; 9 private Set<Course> courses; 10 11 public Student(String id, String name){ 12 this.id = id; 13 this.name = name; 14 this.courses = new HashSet<Course>(); 15 } 16 17 public String getId() { 18 return id; 19 } 20 21 public void setId(String id) { 22 this.id = id; 23 } 24 25 public String getName() { 26 return name; 27 } 28 29 public void setName(String name) { 30 this.name = name; 31 } 32 33 public Set<Course> getCourses() { 34 return courses; 35 } 36 37 public void setCourses(Set<Course> courses) { 38 this.courses = courses; 39 } 40 41 }
测试类:
1 import javax.swing.text.html.parser.Entity; 2 import java.util.HashMap; 3 import java.util.Map; 4 import java.util.Scanner; 5 import java.util.Set; 6 import java.util.Map.*; 7 8 /** 9 * Created by Luts on 2015/12/5. 10 */ 11 public class MapTest { 12 13 //创建Map的学生类型 14 public Map<String, Student> students; 15 16 //初始化学生类型 17 public MapTest(){ 18 this.students = new HashMap<String, Student>(); 19 } 20 21 22 public void testPut(){ 23 Scanner input = new Scanner(System.in); 24 int i = 0; 25 while (i < 3){ 26 System.out.println("输入学生ID"); 27 String ID = input.next(); 28 Student st = students.get(ID); 29 if (st == null){ 30 System.out.println("输入学生姓名"); 31 String name = input.next(); 32 Student newStudent = new Student(ID, name); 33 students.put(ID, newStudent); 34 System.out.println("新添加学生:" + students.get(ID).getName()); 35 i++; 36 }else { 37 System.out.println("该学生ID已被占用"); 38 continue; 39 } 40 } 41 } 42 43 public void testKeySet(){ 44 Set<String> keySet = students.keySet(); //通过keySet方法返回Map值所有“键”的set集合 45 46 //取得students容量 47 System.out.println("总共有:"+students.size() +"个学生"); 48 49 //遍历keySet,取得键对应的值 50 for (String stuID : keySet){ 51 Student st = students.get(stuID); 52 if (st != null){ 53 System.out.println("学生:" + st.getName()); 54 } 55 } 56 57 } 58 59 60 public void testRemove(){ 61 Scanner input = new Scanner(System.in); 62 while (true){ 63 System.out.println("输入要删除的学生ID"); 64 String ID = input.next(); 65 Student st = students.get(ID); 66 if (st == null){ 67 System.out.println("该学生ID不存在"); 68 continue; 69 } 70 System.out.println("成功删除学生:" + students.get(ID).getName()); 71 break; 72 } 73 } 74 75 //通过entrySet方法遍历Maop 76 public void testEntrySet(){ 77 Set<Entry<String, Student>>entrySet = students.entrySet(); 78 for (Entry<String, Student>entry : entrySet){ 79 System.out.println("取得键:" + entry.getKey()); 80 System.out.println("对应的值为:" + entry.getValue().getName()); 81 } 82 } 83 84 public void testModify() { 85 // 提示输入要修改的学生ID 86 System.out.println("请输入要修改的学生ID:"); 87 // 创建一个Scanner对象,去获取从键盘上输入的学生ID字符串 88 Scanner input = new Scanner(System.in); 89 while (true) { 90 // 取得从键盘输入的学生ID 91 String stuID = input.next(); 92 // 从students中查找该学生ID对应的学生对象 93 Student student = students.get(stuID); 94 if (student == null) { 95 System.out.println("该ID不存在!请重新输入!"); 96 continue; 97 } 98 // 提示当前对应的学生对象的姓名 99 System.out.println("当前该学生ID,所对应的学生为:" + student.getName()); 100 // 提示输入新的学生姓名,来修改已有的映射 101 System.out.println("请输入新的学生姓名:"); 102 String name = input.next(); 103 Student newStudent = new Student(stuID, name); 104 students.put(stuID, newStudent); 105 System.out.println("修改成功!"); 106 break; 107 } 108 } 109 110 111 112 public static void main(String[] args){ 113 MapTest mt = new MapTest(); 114 mt.testPut(); 115 mt.testKeySet(); 116 mt.testRemove(); 117 //mt.testEntrySet(); 118 // mt.testModify(); 119 // mt.testEntrySet(); 120 121 } 122 }
5. 比较方法
Comparator接口
TreeSet和TreeMap都按排序顺序存储元素。然而,精确定义到底采用哪种“排序顺序”则是比较方法。在默认情况下,Java采用的是“自然排序”的顺序存储它们的元素,例如A在B的前面,2在3的前面,等等。如果需要用到其他的方法对元素进行排序,可以在构造集合或者映射时,指定一个Comparator对象。
Comparator接口定义了两种方法:compare()和equals()。
compare()方法:

 
Comparable接口
此接口强行对实现它的每个类的对象进行整体排序。此排序被称为该类的自然排序 ,类的 compareTo 方法被称为它的自然比较方法 。实现此接口的对象列表(和数组)可以通过 Collections.sort (和 Arrays.sort )进行自动排序。
int compareTo(T obj) 比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。
Comparator与Comparable的区别
Comparator位于包java.util下,而Comparable位于包java.lang下,Comparable接口将比较代码嵌入自身类中,而后者在一个独立的类中实现比较。 如果类的设计师没有考虑到Compare的问题而没有实现Comparable接口,可以通过 Comparator来实现比较算法进行排序,并且为了使用不同的排序标准做准备,比如:升序、降序。
关于比较器,更多参阅:http://blog.csdn.net/cz1029648683/article/details/6666855
6.集合类性能效率总结
| 接口 | 实现类 | 保持插入顺序 | 可重复 | 排序 | 使用说明 | 
| List | ArrayList | Y | Y | N | 长于随机访问元素;但插入、删除元素较慢(数组特性)。 | 
| LinkedList | Y | Y | N | 插入、删除元素较快,但随即访问较慢(链表特性)。 | |
| Set | HashSet | N | N | N | 使用散列,最快的获取元素方法。 | 
| TreeSet | N | N | Y | 将元素存储在红-黑树数据结构中。默认为升序。 | |
| LinkedHashSet | Y | N | N | 使用散列,同时使用链表来维护元素的插入顺序。 | |
| Map | HashMap | N | N | N | 使用散列,提供最快的查找技术。 | 
| TreeMap | N | N | Y | 默认按照比较结果的升序保存键。 | |
| LinkedHashMap | Y | N | N | 按照插入顺序保存键,同时使用散列提高查找速度。 | 
 
                     
                    
                 
                    
                 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号