【黑马程序员】Java集合类
来源:互联网 发布:周末网络国债理财 编辑:程序博客网 时间:2024/06/07 00:19
-------android培训、java培训、期待与您交流! ----------
1. Java集合
Java集合类也成Java容器类,是Java中实用的工具,实现了一些常用的数据结构和方法,方便开发者调用。集合类和数组不一样,数组中可以存放基本类型的变量也可以存放对象,容器类中只能存放对象(实际上是对象的引用)。Java的集合类主要由两个接口派生而出:Collection和Map,Collection和Map是Java集合框架的根接口,这两个接口又包含了一些子接口或实现类,如下图是Collection接口的继承树:
如图所示:Set和List接口是Collection的两个子接口,它们分别代表了无序集合和有序集合;Queue是Java提供的队列实现,有点类似于List。
下图显示的是Map接口的子接口及其及继承树:
所有的Map实现类用于保存具有映射关系的数据,上图显示了Map的众多实现类,它们的功能各有不同,但都是存放的键值对。
2.Set集合
Set集合类似于一个罐子,放进去的元素是无序的。Set集合类似于Collection但Set集合不能存放相同的元素。
Set判断两个元素是否相同不是通过 == 而是 equals() 方法。
1) HashSet类
Hash是Set的典型实现类,也是Set中使用最多的类。HashSet使用Hash算法存放元素,有很好的存取和查找性能。
特点:
①不能保证元素的排列顺序。
②不同步。当两个线程同时访问一个HashSet时,假设他们同时修改HashSet元素,必须通过代码保证同步性。
③集合元素可以是null。
判断元素相同标准:
HashSet通过equals()以及hashCode()两个方法判断两个元素是否相同。如果两个元素euqals()比较返回true但hashCode不同,HashCode同样认为这是两个不同的元素。
示例:
class TestA { public boolean equals(Object obj){ return true; }} //类B的hashCode()方法总是返回1,但没有重写其equals()方法class TestB { public int hashCode(){ return 1; }} //类C的hashCode()方法总是返回2,且有重写其equals()方法class TestC { public int hashCode(){ return 2; } public boolean equals(Object obj) { return true; }}public class HashSetTest { public static void main(String[] args) { HashSet hs = new HashSet(); //分别向hs集合中添加两个TestA对象,两个TestB对象,两个TestC对象 hs.add(new TestA()); <span style="font-family: Arial, Helvetica, sans-serif;">hs</span><span style="font-family: Arial, Helvetica, sans-serif;">.add(new TestA()); //返回true,添加成功。两个对象的equals()虽然为true,但hashCode不同,HashSet视为不同对象</span> <span style="font-family: Arial, Helvetica, sans-serif;">hs</span>.add(new TestB()); hs.add(new TestB()); <span style="font-family: Arial, Helvetica, sans-serif;">//返回true,添加成功。对象的hashCode恒定返回2,所以相等,但两个对象指向不同。使用Object类的equals()方法进行比较时返回false, ,HashSet视为不同对象</span> hs.add(new TestC()); hs.add(new TestC()); //添加失败,两个对象的equals()返回true,且hashCode返回2相等,所以无法添加元素,返回false System.out.println(hs); }}
HashSet中euqlas()返回ture并且hashCode()相等才判断为同一元素,如果euqals()为true但hashCode()不同,则存放元素时按hash值存放。如果hashCode相等,但equals为false,则会在原来hashcode位置使用链式存放,会导致性能下降。
2) LinkedHashSet
使用链表维护容器内元素的顺序,输出时与添加元素的顺序一致。其他特性与HashSet一致。
示例:
public class LinkedHashSetTest { public static void main(String[] args) { LinkedHashSet lhs = new LinkedHashSet(); lhs.add("天空飘来5个字"); lhs.add("那都不是事"); System.out.println(lhs); //删除 天空飘来5个字 lhs.remove("天空飘来5个字"); //重新添加 天空飘来5个字 lhs.add("天空飘来5个字"); System.out.println(lhs); }}
3)TreeSet
TreeSet是SortedSet接口的实现类。TreeSet中的元素总是有序的。
TreeSet采用红黑树存放元素。当一个元素被添加到TreeSet中时,系统会调用对象的compareTo(Object obj)方法与容器的其他元素比较确定元素的存放位置。所以添加到TreeSet的元素必须实现Comparable接口,否则在添加时会抛出ClassCastException异常。如以下代码所示:
class Tmp {}public class TreeSetExceptionTest {public static void main(String[] args) {TreeSet ts = new TreeSet();//向TreeSet集合中添加两个Tmp对象ts.add(new Tmp()); //可以正常添加,因为容器没有元素,不用进行比较//由于Tmp类未实现Comparable接口所以,当向TreeSet中插入第2个元素时,系统会抛出异常ts.add(new Tmp()); }}
对于TreeSet而言,判断两个元素是否相等唯一的条件是compareTo()方法返回0;
总结:HashSet和TreeSet是Set的两个典型实现。一般情况下HashSet的性能好于TreeSet,因为TreeSet需要维护红黑树来保持集合元素的次序。HashSet的子类LinkedHashSet的性能没有HashSet高,同样是要维护一个链表。但应为有链表所以LinkedHashSet的遍历速度优于HashSet,EnumSet的性能最好。
3. List集合
List集合代表一个有序的,可重复的集合,集合的中每个元素都有对应的索引,可通过该索引随机访问集合中的元素。对应的数据结构为线性表。1) List接口
List接口是Collection接口的子接口,扩展了一些线性表特有的方法:
示例:
public class ListTest { public static void main(String[] args) { List names = new ArrayList(); //向names集合中添加三个元素 names.add(new String("")); names.add(new String("张三")); names.add(new String("李四")); System.out.println(names); //将新字符串对象插入在第二个位置 names.add(1 , new String("王五")); for (int i = 0 ; i < names.size() ; i++ ) { System.out.println(names.get(i)); } //删除第三个元素 names.remove(2); System.out.println(names); //判断指定元素在List集合中位置:输出1,表明位于第二位 System.out.println(names.indexOf(new String("王五"))); //将第二个元素替换成新的字符串对象 names.set(1, new String("王五")); System.out.println(names); //将names集合的第二个元素(包括) //到第三个元素(不包括)截取成子集合 System.out.println(names.subList(1 , 2)); }}
List判断元素相等是通过equals()方法。List接口中的indexOf()、remove()等需要差早和比较元素的方法都是通过equals()方法确定元素是否相等,而不是通过判断元素的引用对象是否是同一对象。
示例:
class A { public boolean equals(Object obj) { return true; }}public class ListTest2 { public static void main(String[] args) { List names = new ArrayList(); names.add(new String("张三")); names.add(new String("李四")); names.add(new String("王五")); System.out.println(names); //删除集合中A对象,将导致第一个元素被删除 names.remove(new A()); System.out.println(names); //删除集合中A对象,再次删除集合中第一个元素 names.remove(new A()); System.out.println(names); }}
2) ArrayList和Vertor实现类
ArrayList和Vertor是List的两个典型实现类。两者内部使用数组存放元素,所以其内部有一个Object[]的动态数组。
ArrayList和Vertor使用initialCapacity设置数组的长度,当元素数量超出数组的长度是,数组容量会自动增加。用户在使用两个集合类是无需关心initialCapacity的大小,系统会自动以及增长。当需要一次性添加大量元素时,可以将initialCapacity属性设置为一个较大的数字已减少系统扩充数组容量的次数,提升性能。
示例:
public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(20); //设置初始化容量为20,如不设置默认容量为10 list.ensureCapacity(500); //使用ensureCapacity()方法重行设置数组容量 list.trimToSize(); //将ArrayList长度缩减到当前数组当前元素的数量,可以使ArrayList占用的空间最小化 }
Vertor与ArrayList不同的是前者是线程安全的,当性能较ArrayList低,一般情况下不推荐使用。
4. Queue集合
Queue用于模拟队列这种数据结构,队列是指FIFO的容器。队列的头部保存在队列中存放时间最长的元素,队列的尾部保存在队列中存放时间最短的元素。新元素插入在队列的尾部,访问元素操作会返回队列头部的元素。Queue定义了如下几个方法:
- vod add(Object e)将指定元素插入队尾
- Object elenent() 获取队列头部的元素,但不删除该元素
- boolean offer(Object e)将指定元素加入此队列的尾部,性能较好
- Object peek()获取队列头部的元素,但不删除该元素。
- Object poll()获取队列头部的元素,并删除该元素。
这是一个标准额队列实现类,PriorityQueue保存队列元素的顺序并不是按照加入的顺序,而是按队列元素的大小进行排序。当调用peek()和poll()方法是,是去除队列中最小的元素。下面是该类的用法:
public class PriorityQueueTest { public static void main(String[] args) { PriorityQueue pq = new PriorityQueue(); //下面代码依次向pq中加入四个元素 pq.offer(6); pq.offer(-3); pq.offer(9); pq.offer(0); //输出pq队列,并不是按元素的加入顺序排列, //而是按元素的大小顺序排列,输出[-3, 0, 9, 6] System.out.println(pq); //访问队列第一个元素,其实就是队列中最小的元素:-3 System.out.println(pq.poll()); }}注意:PriorityQueue不允许插入null对象
2)Deque和ArrayDeque实现类
Deque是Queue的子接口,它代表一个双端队列,Deque不仅可以当作队列使用还可以当作栈使用。Deque提供了一个典型的实现类:ArrayDeque,从该名称来看,这是一个基于数组实现的双端队列。下面示例将ArrayDeque当作堆栈来使用:
public class ArrayDequeTest { public static void main(String[] args) { ArrayDeque stack = new ArrayDeque(); //依次将三个元素push入"栈" stack.push("大学英语"); stack.push("高等数学"); stack.push("大学物理"); //输出:[大学英语, 高等数学 , 大学物理] System.out.println(stack); //访问第一个元素,但并不将其pop出"栈",输出:大学物理 System.out.println(stack.peek()); //依然输出:[大学英语, 高等数学 , 大学物理] System.out.println(stack); //pop出第一个元素,输出:大学物理 System.out.println(stack.pop()); //输出:[大学英语, 高等数学] System.out.println(stack); }}
5. HashMap和Hashtable集合
它们都是Map接口的实现类,它们之间的区别如下:Hashtable是一个线程安全的Map实现,但HashMap是线程不安全的实现,所以HashMap比Hashtable的性能高一点;但如果有多了线程访问同一个Map对象时,使用Hashtable实现类更好。
Hashtable不允许使用Null作为key和value,但HashMap可以使用null作为key或者value。
下面演示null作为HashMap的key和value的情况:
public class NullInHashMap { public static void main(String[] args) { HashMap hm = new HashMap(); //试图将两个key为null的key-value对放入HashMap中 hm.put(null , null); hm.put(null , null); //① //将一个value为null的key-value对放入HashMap中 hm.put("a" , null); //② //输出Map对象 System.out.println(hm); }}HashMap判断两个key相等的标准是:两个key通过equals()比较返回true,两个key的hashCode值相等。
HashMap判断两个value相等的标准是:两个value通过equals()表叫返回true。下面程序演示了hashtable判断两个key相等和两个value相等的标准。
class A { int count; public A(int count) { this.count = count; } //根据count的值来判断两个对象是否相等。 public boolean equals(Object obj) { if (obj == this) return true; if (obj!=null && obj.getClass()==A.class) { A a = (A)obj; return this.count == a.count; } return false; } //根据count来计算hashCode值。 public int hashCode() { return this.count; }}class B { //重写equals()方法,B对象与任何对象通过equals()方法比较都相等 public boolean equals(Object obj) { return true; }}public class HashtableTest { public static void main(String[] args) { Hashtable ht = new Hashtable(); ht.put(new A(60000) , "大学英语"); ht.put(new A(87563) , "高等数学"); ht.put(new A(1232) , new B()); System.out.println(ht); //只要两个对象通过equals比较返回true, //Hashtable就认为它们是相等的value。 //由于Hashtable中有一个B对象, //它与任何对象通过equals比较都相等,所以下面输出true。 System.out.println(ht.containsValue("测试字符串")); //① //只要两个A对象的count相等,它们通过equals比较返回true,且hashCode相等 //Hashtable即认为它们是相同的key,所以下面输出true。 System.out.println(ht.containsKey(new A(87563))); //② //下面语句可以删除最后一个key-value对 ht.remove(new A(1232)); //③ //通过返回Hashtable的所有key组成的Set集合, //从而遍历Hashtable每个key-value对 for (Object key : ht.keySet()) { System.out.print(key + "---->"); System.out.print(ht.get(key) + "\n"); } }}
- 黑马程序员:java集合类
- 黑马程序员-----java集合类
- 【黑马程序员】Java集合类
- 黑马程序员 java 集合
- 黑马程序员---java集合
- 黑马程序员---集合【java】
- 黑马程序员-------Java集合
- 黑马程序员-java集合
- 黑马程序员--Java集合
- 黑马程序员----java集合
- 黑马程序员----JAVA集合
- 黑马程序员--Java集合
- 黑马程序员--java集合
- 黑马程序员--java集合
- 黑马程序员---java---集合
- 黑马程序员Java----集合
- 黑马程序员 JAVA集合
- 黑马程序员-Java集合
- 传智播客基础班学习总结
- OC内存管理初级演练
- hdu 2141
- HDU 4952 Number Transformation (找规律)
- 马士兵struts2视频教程第二十九集
- 【黑马程序员】Java集合类
- hdu 2005 第几天?
- 1408141706-hd-Moving Tables.cpp
- hdu 4950 Monster--2014 Multi-University Training Contest 8
- day04-05数组
- poj 1844 Sum ( 数学思维 )
- 忘记了用户,哎!怎么办
- Harfbuzz 测试程序
- hdu 4952 Number Transformation