容器

集合架构

  • Collection 接口存储一组不唯一,无序的对象

    • List 接口存储一组不唯一,有序(索引顺序)的对象

    • Set 接口存储一组唯一,无序的对象

  • Map接口存储一组键值对象,提供key到value的映射

    • Key 唯一 无序

    • value 不唯一 无序

List

  • List

    • 特点:有序 不唯一(可重复)
  • ArrayList(线程不安全,效率高) 线性表中的顺序表
    • 在内存中分配连续的空间,实现了长度可变的数组
    • 优点:遍历元素和随机访问元素的效率比较高
    • 缺点:添加和删除需大量移动元素效率低,按照内容查询效率低,
  • LinkedList (线程不安全,效率高)线性表中双向链表
    • 采用双向链表存储方式。
    • 缺点:遍历和随机访问元素效率低下
    • 优点:插入、删除元素效率比较高(但是前提也是必须先低效率查询才可。如果插入删除发生在头尾可以减少查询次数)

  • Vector (线程安全,效率底)和ArrayList一样(唯一区就是一个线程安全,一个线程不安全)

  1 public class MyArrayList /*implements List*/ {
  2     
  3     private Object[] elementData;
  4     private int size;
  5     
  6     
  7     public int size(){
  8         return size;
  9     }
 10     
 11     public boolean isEmpty(){
 12         return size==0;
 13     }
 14     
 15     public MyArrayList(){
 16         this(10);
 17     }
 18     
 19     public MyArrayList(int initialCapacity){
 20         if(initialCapacity<0){
 21             try {
 22                 throw new Exception();
 23             } catch (Exception e) {
 24                 e.printStackTrace();
 25             }
 26         }
 27         elementData = new Object[initialCapacity];
 28     }
 29     
 30     public void add(Object obj){
 31         if(size==elementData.length){
 32             Object[] newArray = new Object[size*2+1];
 33             System.arraycopy(elementData, 0, newArray, 0, elementData.length);
 34             elementData = newArray;
 35         }
 36         elementData[size++]=obj;
 37     }
 38     
 39     public Object get(int index){
 40         rangeCheck(index);
 41         
 42         return elementData[index];
 43     }
 44     
 45     public void remove(int index){
 46         rangeCheck(index);
 47         int numMoved = size - index - 1;
 48         if (numMoved > 0){
 49             System.arraycopy(elementData, index+1, elementData, index,
 50                     numMoved);
 51         }
 52         elementData[--size] = null;
 53     }
 54 
 55     public void remove(Object obj){
 56         for(int i=0;i<size;i++){
 57             if(get(i).equals(obj)){
 58                 remove(i);
 59             }
 60         }
 61     }
 62     
 63     public Object set(int index,Object obj){
 64         rangeCheck(index);
 65 
 66         Object oldValue =  elementData[index];
 67         elementData[index] = obj;
 68         return oldValue;
 69     }
 70     
 71     public void add(int index,Object obj){
 72         rangeCheck(index);
 73         
 74         ensureCapacity(); 
 75         
 76         System.arraycopy(elementData, index, elementData, index + 1,
 77                  size - index);
 78         elementData[index] = obj;
 79         size++;
 80     }
 81     
 82     private void ensureCapacity(){
 83                 if(size==elementData.length){
 84                     Object[] newArray = new Object[size*2+1];
 85                     System.arraycopy(elementData, 0, newArray, 0, elementData.length);
 86                     elementData = newArray;
 87                 }
 88     }
 89     
 90     
 91     private void rangeCheck(int index){
 92         if(index<0||index>=size){
 93             try {
 94                 throw new Exception();
 95             } catch (Exception e) {
 96                 e.printStackTrace();
 97             }
 98         }
 99     }
100     
101     
102     public static void main(String[] args) {
103         MyArrayList list = new MyArrayList(3);
104         list.add("333");
105         list.add("444");
106         list.add("5");
107         list.add("344433");
108         list.add("333");
109         list.add("333");
110         System.out.println(list.size()); 
111         list.remove("444");
112         System.out.println(list.size());
113     }
114 
115 }
手动实现ArrayList
  1 public class Node {
  2     private Node previous;
  3     private Object obj;
  4     private Node next;
  5     
  6     public Node() {
  7     }
  8     
  9     public Node(Node previous, Object obj, Node next) {
 10         super();
 11         this.previous = previous;
 12         this.obj = obj;
 13         this.next = next;
 14     }
 15 
 16     public Node getPrevious() {
 17         return previous;
 18     }
 19 
 20     public void setPrevious(Node previous) {
 21         this.previous = previous;
 22     }
 23 
 24     public Object getObj() {
 25         return obj;
 26     }
 27 
 28     public void setObj(Object obj) {
 29         this.obj = obj;
 30     }
 31 
 32     public Node getNext() {
 33         return next;
 34     }
 35 
 36     public void setNext(Node next) {
 37         this.next = next;
 38     }
 39 }
 40 
 41 
 42     private void rangeCheck(int index){
 43         if(index<0||index>=size){
 44             try {
 45                 throw new Exception();
 46             } catch (Exception e) {
 47                 e.printStackTrace();
 48             }
 49         }
 50     }
 51     
 52     public Object get(int index){   //2
 53         rangeCheck(index);
 54         // 0 1 2 3 4
 55         Node temp = node(index);
 56         if(temp!=null){
 57             return temp.getObj();
 58         }
 59         return null;
 60     }
 61     
 62     public Node node(int index){
 63         Node temp = null;
 64         if(first!=null){
 65             if (index < (size >> 1)) {// size >> 1 == size/2
 66                 temp = first;
 67                 for(int i=0;i<index;i++){
 68                     temp = temp.getNext();
 69                 }
 70             }else{
 71                 temp = last;
 72                 for (int i = size - 1; i > index; i--){
 73                     temp = temp.getPrevious();
 74                 }
 75             }
 76             
 77         }
 78 //        LinkedList l;
 79         return temp;
 80     }
 81     
 82     
 83     public void remove(int index){
 84         Node temp = node(index);
 85         
 86         if(temp!=null){
 87             Node up = temp.getPrevious();
 88             Node down = temp.getNext();
 89             up.setNext(down);
 90             down.setPrevious(up);
 91             size--;
 92         }
 93         
 94     }
 95     
 96     public void add(int index,Object obj){
 97         Node temp = node(index);
 98         
 99         Node newNode = new Node();
100         newNode.setObj(obj);
101         
102         if(temp!=null){
103             Node up = temp.getPrevious();
104             up.setNext(newNode);
105             newNode.setPrevious(up);
106             
107             newNode.setNext(temp);
108             temp.setPrevious(newNode);
109             
110             size++;
111         }
112     }
113     
114     
115     
116     
117     
118     public static void main(String[] args) {
119         MyLinkedList list = new MyLinkedList();
120         list.add("aaa");
121         list.add("bbb");
122 //        list.add(1,"BBBB");
123         list.add("ccc");
124         list.add("ddd");
125         list.add("eee");
126 //        list.remove(1);
127         System.out.println(list.get(3)); 
128     }
129     
130 
131 }
手动实现LinkedList

Set

  • Set
    • 特点:无序 唯一(不重复)
  • HashSet(底层是HashMap)
    • 采用HashMap哈希表存储结构(神奇的结构)
    • 优点:添加速度快 查询速度快 删除速度快
    • 缺点:无序
  • LinkedHashSet
    • 采用哈希表存储结构,同时使用链表维护次序
    • 有序(添加顺序)
  • TreeSet
    • 采用二叉树(红黑树)的存储结构
    • 优点:有序 查询速度比List快(按照内容查询)
    • 缺点:查询速度没有HashSet快

  • Set常用方法
    • Set相对Collection没有增加任何方法
  • Set的遍历方法
    • for-each
    • Iterator迭代器
    • 无法使用for进行遍历(因为无序,所以没有get(i))
  • HashSet、HashMap或Hashtable中对象唯一性判断
    • 重写(一般使用idea生成重写代码即可)其hashCode()和equals()方法 

    • Java中规定,两个内容相等的对象,应该具有相等的hashCode,反之,hashCode相同,内容不一定相同
      - 比较对象是先在数组中找到hashCode对应的那个链表,然后在遍历链表执行equals,所以两个内容相等的对象,应该具有相等的hashCode,hashCode相同,内容不一定相同

  • TreeSet中指明排序依据
    • 实现Comparable接口
    • 创建实现Compator接口的类。

 1 public class MyHashSet {
 2 
 3     HashMap map;
 4     private static final Object PRESENT = new Object();
 5 
 6     public MyHashSet(){
 7         map = new HashMap();
 8     }
 9     
10     public int size(){
11         return map.size();
12     }
13     
14     public void add(Object o){
15         map.put(o, PRESENT);
16     }
17     
18     public static void main(String[] args) {
19         MyHashSet s = new MyHashSet();
20         s.add("aaa");
21         s.add(new String("aaa"));
22         System.out.println(s.size());
23     }
24 
25 }
手动实现HashSet

Map

  • Map(底层实现:数据+链表)

    • 特点 key-value映射

  • HashMap(线程不安全,效率高)Hashtable(线程安全,效率低,其他的和HashMap一样)
    • Key无序 唯一 (Set)
    • Value 无序 不唯一 (Collection)

  • LinkedHashMap
    • 有序的HashMap 速度快
  • TreeMap
    • 有序 速度没有hash快
  • 问题:Set和Map有关系吗?
    • 采用了相同的数据结构,只用于map的key存储数据,就是Set

 1 /**
 2  * 1. 提高查询的效率
 3  * 2. Map底层:数组 + 链表
 4  */
 5 public class MyMap {
 6 
 7     LinkedList[]  arr  = new LinkedList[9]; //Map的底层结构就是:数组+链表!
 8     int size;
 9     
10     public void put(Object key,Object value){
11         MyEntry e = new MyEntry(key,value);
12         // 每个对象在内存中都有一个地址,hashCode是根据对象的内存地址生成的序列码
13         int hash = key.hashCode();
14         hash = hash<0?-hash:hash;
15         
16         int a = hash%arr.length;
17         if(arr[a]==null){
18             LinkedList list = new LinkedList();
19             arr[a] = list;
20             list.add(e);
21         }else{
22             LinkedList list = arr[a];
23             for(int i=0;i<list.size();i++){
24                 MyEntry e2 = (MyEntry) list.get(i);
25                 if(e2.key.equals(key)){
26                     e2.value = value;  //键值重复直接覆盖!
27                     return;
28                 }
29             }
30             
31             arr[a].add(e);
32         }
33         //a:1000-->1   b:10000-->13
34     }
35 
36     public Object get(Object key){
37         int a = key.hashCode()%arr.length;
38         if(arr[a]!=null){
39             LinkedList list = arr[a];
40             for(int i=0;i<list.size();i++){
41                 MyEntry e = (MyEntry) list.get(i);
42                 if(e.key.equals(key)){
43                     return e.value;
44                 }
45             }
46         }
47         
48         return null;
49     }
50     
51     public static void main(String[] args) {
52         MyMap m = new MyMap();
53         m.put("高琪", new Wife("杨幂"));
54         m.put("高琪", new Wife("李四"));
55         Wife w = (Wife) m.get("高琪");
56         System.out.println(w.name); 
57     }
58 
59 }
60 
61 class MyEntry {
62     Object key;
63     Object value;
64 
65     public MyEntry(Object key, Object value) {
66         super();
67         this.key = key;
68         this.value = value;
69     }
70 }
手动实现Map

Iterator

  • 所有集合类均未提供相应的遍历方法,而是把把遍历交给迭代器完成。迭代器为集合而生,专门实现集合遍历
  • Iterator是迭代器设计模式的具体实现
  • Iterator方法
    • boolean hasNext(): 判断是否存在另一个可访问的元素
    • Object next(): 返回要访问的下一个元素
    • void remove(): 删除上次访问返回的对象。
  • 问题:可以使用Iterator遍历的本质是什么
    • 实现Iterable接口

  • For-each循环
    • 增强的for循环,遍历array 或 Collection的时候相当简便
    • 无需获得集合和数组长度,无需使用索引访问元素,无需循环条件
    • 遍历集合时底层调用Iterator完成操作

  • For-each缺陷:
    • 数组:
      • 不能方便的访问下标值
      • 不要在for-each中尝试对变量赋值,只是一个临时变量
    • 集合:
      • 与使用Iterator相比,不能方便的删除集合中的内容

  • For-each总结:
    • 除了简单遍历并读出其中的内容外,不建议使用增强for

  • ListIterator和Iterator的关系
    • public interface ListIterator<E> extends Iterator<E>
    • 都可以遍历List

  • ListIterator和Iterator的区别
    • 使用范围不同
    • Iterator可以应用于更多的集合,Set、List和这些集合的子类型。
    • 而ListIterator只能用于List及其子类型。
    • 遍历顺序不同
    • Iterator只能顺序向后遍历; ListIterator还可以逆序向前遍历
    • Iterator可以在遍历的过程中remove();ListIterator可以在遍历的过程中remove()、add()、set()
    • ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。

泛型

  • 起因:
    • JDK1.4以前类型不明确:
    • 装入集合的类型都被当作Object对待,从而失去自己的实际类型。
    • 从集合中取出时往往需要转型,效率低,容易产生错误(转型的类型可能不是你存入的类型)。
  • 解决办法:
    • 泛型,在定义集合的时候同时定义集合中对象的类型
  • 好处:
    • 增强程序的可读性和安全性,在编译的时候就进行了类型检查

  注意(数组没有泛型):

    泛型类: 修饰词 Class 类名<字母> {}

      • 在接口中泛型字母只能使用在方法中,不能用于全局常量

      • 泛型只能使用引用类型,不能使用基本数据类型

      • 泛型只能访问对象信息,不能修改对象信息(因为泛型的类型没有定)

      • 泛型声明时不能使用在静态属性和静态方法上(泛型是在使用的时候确定类型,静态属性,静态方法等是在编译的时候确定类型)

      • 泛型使用字母的含义

        T Type 表示类型

        K V分别表示键值中的Key Value

        E 代表Element

        ? 不确定类型

    泛型方法:修饰词 static <字母> 方法名(字母){}

排序容器

  1. TreeSet : 确保元素实体可以排序

    注意:TreeSet在添加数据时排序,添加完成后,更改TreeSet中元素的数据不会更改原来的顺序,在使用过程中不要修改数据,否则可能重复,如果要达到不能修改数据的要求,则在元素的属性上加final

    1)Set接口对比:

      HashSet不可以排序,存放在HashSet中的元素必须重写hashCode和equals方法

      TreeSet不需要重写hashCode和equals方法,因为在排序的过程中无非就是正数、负数、零,当等于零的时候就表示相等,就可以去重了

    2)确保元素可以排序,实现java.lang.Comparable,重写compareTo

      new TreeSet();

    3)提供元素比较器(排序业务类)实现java.util.Comparator,重写compare

      new TreeSet(Comparator<? super E> comparator);

  1 public class Person {
  2     private final String name;//名称
  3     private final int handsome;//帅气指数
  4     
  5     public Person() {
  6         name =null;
  7         handsome =0;
  8     }
  9 
 10     public Person(String name, int handsome) {
 11         super();
 12         this.name = name;
 13         this.handsome = handsome;
 14     }
 15 
 16     public String getName() {
 17         return name;
 18     }
 19 
 20     public int getHandsome() {
 21         return handsome;
 22     }
 23     
 24     @Override
 25     public String toString() {
 26         return "姓名:"+this.name+",帅气指数:"+this.handsome+"\n";
 27     }
 28 }
 29 
 30 /**
 31  * 提供了 解耦的方式:业务排序类
 32  * @author Administrator
 33  *
 34  */
 35 public class TreeSetDemo {
 36 
 37     /**
 38      * @param args
 39      */
 40     public static void main(String[] args) {
 41         Person p1 =new Person("您",100);
 42         Person p2 =new Person("刘德华",1000);
 43         Person p3 =new Person("梁朝伟",1200);
 44         Person p4 =new Person("老裴",50);
 45         
 46         //依次存放到TreeSet容器中,使用排序的业务类(匿名内部类)
 47         TreeSet<Person> persons =new TreeSet<Person>(
 48                     new java.util.Comparator<Person>(){
 49 
 50                         @Override
 51                         public int compare(Person o1, Person o2) {
 52                             return -(o1.getHandsome()-o2.getHandsome());
 53                         }
 54                         
 55                     }
 56                 );
 57         persons.add(p1);
 58         //TreeSet 在添加数据时排序
 59         persons.add(p2);
 60         persons.add(p3);
 61         persons.add(p4);
 62         
 63         System.out.println(persons);
 64         
 65         /*
 66         //改变数据
 67         p4.setHandsome(100);
 68         p4.setName("您");
 69         */ 
 70         //p4 与p1 内容重复 
 71         System.out.println(persons);
 72     }
 73 }
 74 
 75 
 76 public class Worker implements java.lang.Comparable<Worker> {
 77     //工种
 78     private String type;
 79     //工资
 80     private double salary;
 81     public Worker() {
 82         // TODO Auto-generated constructor stub
 83     }
 84     
 85     
 86     public Worker(String type, double salary) {
 87         super();
 88         this.type = type;
 89         this.salary = salary;
 90     }
 91 
 92 
 93     public String getType() {
 94         return type;
 95     }
 96     public void setType(String type) {
 97         this.type = type;
 98     }
 99     public double getSalary() {
100         return salary;
101     }
102     public void setSalary(double salary) {
103         this.salary = salary;
104     }
105 
106     /**
107      * 按工资升序
108      */
109     @Override
110     public int compareTo(Worker o) {
111         return this.salary>o.salary?1:( this.salary==o.salary?0:-1);
112     }
113     
114     @Override
115     public String toString() {
116         return "工种:"+this.type+",工资:"+this.salary+"\n";
117     }
118     
119 }
120 
121 /**
122  * 实体类实现Comparable 接口的应用
123  * @author Administrator
124  *
125  */
126 public class TreeSetDemo2 {
127 
128     /**
129      * @param args
130      */
131     public static void main(String[] args) {
132         Worker w1 =new Worker("垃圾回收员",12000);
133         Worker w2 =new Worker("农民工",8000);
134         Worker w3 =new Worker("程序猿",5000);
135         
136         TreeSet<Worker> employees =new TreeSet<Worker>();
137         employees.add(w1);
138         employees.add(w2);
139         employees.add(w3);
140         System.out.println(employees);
141         
142     }
143 
144 }
实例代码

  2. TreeMap : 确保key可以排序或者提供比较器

    1)确保key可以排序,实现java.lang.Comparable,重写compareTo

      new TreeMap();

    2)提供key比较器(排序业务类)实现java.util.Comparator,重写compare

      new TreeMap(Comparator<? super E> comparator);

  1 public class Person {
  2     private final String name;//名称
  3     private final int handsome;//帅气指数
  4     
  5     public Person() {
  6         name =null;
  7         handsome =0;
  8     }
  9 
 10     public Person(String name, int handsome) {
 11         super();
 12         this.name = name;
 13         this.handsome = handsome;
 14     }
 15 
 16     public String getName() {
 17         return name;
 18     }
 19 
 20     public int getHandsome() {
 21         return handsome;
 22     }
 23     
 24     @Override
 25     public String toString() {
 26         return "姓名:"+this.name+",帅气指数:"+this.handsome+"\n";
 27     }
 28 
 29 }
 30 
 31 /**
 32  * 提供了 解耦的方式:业务排序类
 33  * @author Administrator
 34  *
 35  */
 36 public class TreeMapDemo {
 37 
 38     /**
 39      * @param args
 40      */
 41     public static void main(String[] args) {
 42         Person p1 =new Person("您",100);
 43         Person p2 =new Person("刘德华",1000);
 44         Person p3 =new Person("梁朝伟",1200);
 45         Person p4 =new Person("老裴",50);
 46         
 47         TreeMap<Person,String> map =new TreeMap<Person,String>(new java.util.Comparator<Person>(){
 48 
 49             @Override
 50             public int compare(Person o1, Person o2) {
 51                 return -(o1.getHandsome()-o2.getHandsome());
 52             }
 53             
 54         } );
 55         map.put(p1, "bjsxt");
 56         map.put(p2, "bjsxt");
 57         map.put(p3, "bjsxt");
 58         map.put(p4, "bjsxt");
 59         
 60         //查看键
 61         Set<Person> persons =map.keySet();
 62         System.out.println(persons);
 63     }
 64 }
 65 
 66 public class Worker implements java.lang.Comparable<Worker> {
 67     //工种
 68     private String type;
 69     //工资
 70     private double salary;
 71     public Worker() {
 72         // TODO Auto-generated constructor stub
 73     }
 74     
 75     
 76     public Worker(String type, double salary) {
 77         super();
 78         this.type = type;
 79         this.salary = salary;
 80     }
 81 
 82 
 83     public String getType() {
 84         return type;
 85     }
 86     public void setType(String type) {
 87         this.type = type;
 88     }
 89     public double getSalary() {
 90         return salary;
 91     }
 92     public void setSalary(double salary) {
 93         this.salary = salary;
 94     }
 95 
 96     /**
 97      * 按工资升序
 98      */
 99     @Override
100     public int compareTo(Worker o) {
101         return this.salary>o.salary?1:( this.salary==o.salary?0:-1);
102     }
103     
104     @Override
105     public String toString() {
106         return "工种:"+this.type+",工资:"+this.salary+"\n";
107     }
108     
109 }
110 
111 /**
112  * 实体类实现Comparable 接口的应用
113  * @author Administrator
114  *
115  */
116 public class TreeMapDemo02 {
117 
118     /**
119      * @param args
120      */
121     public static void main(String[] args) {
122         Worker w1 =new Worker("垃圾回收员",12000);
123         Worker w2 =new Worker("农民工",8000);
124         Worker w3 =new Worker("程序猿",5000);
125         
126         TreeMap<Worker,String > employees =new TreeMap<Worker,String >();
127         employees.put(w1,"bjsxt");
128         employees.put(w2,"bjsxt");
129         employees.put(w3,"bjsxt");
130         System.out.println(employees.keySet());
131     }
132 
133 }
示例代码

java.util接口 Queue<E>

public interface Queue<E>extends Collection<E>

Queue:单向
  队列通常 FIFO(先进先出)
  优先级队列和堆栈LIFO(后进先出)
  抛出异常 返回特殊值
插入 add(e) offer(e)
移除 remove() poll()
检查 element() peek()

 Deque:双向(两端访问)

   deque 是“double ended queue(双端队列)”的缩写,是一种具有队列和栈的性质的数据结构,双端队列中的元素可以从两端弹出,其限定插入和删除操作在表的两端进行。

      此接口扩展了Queue接口,在将双端队列用作队列时,将得到FIFO行为

   可用作LIFO堆栈

  第一个元素(头部) 最后一个元素(尾部)
  抛出异常 特殊值 抛出异常 特殊值
插入 addFirst(e) offerFirst(e) addLast(e) offerLast(e)
移除 removeFirst() pollFirst() removeLast() pollLast()
检查 getFirst() peekFirst() getLast() peekLast()

Enumeration

  枚举Enumeration(线程安全的)作用和Iterator类似,都是输出数据(这个接口比较古老,被Iterator取代)

  方法:hasMoreElements() nextElement() 

  Vector的elements()返回的就是Enumeration

 1 /**
 2  * Enumeration 的使用
 3  * 1、判断  hasMoreElements()
 4  * 2、获取 nextElement()
 5  * 
 6  * Vector 的 elements()方法
 7  * 
 8  * 
 9  * @author Administrator
10  *
11  */
12 public class Demo01 {
13 
14     /**
15      * @param args
16      */
17     public static void main(String[] args) {
18         Vector<String> vector =new Vector<String>();
19         vector.add("javase");
20         vector.add("html");
21         vector.add("oracle");
22         
23         //遍历该Vector
24         Enumeration<String> en =vector.elements();
25         while(en.hasMoreElements()){
26             System.out.println(en.nextElement());
27         }
28     }
29 }
示例代码

  Enumeration的子类StringTokenizer等同于String split() 字符串分割,但是不支持正则表达式StringTokenizer(String str, String delim) 

 1 /**
 2  * Enumeration 子类
 3  * StringTokenizer:String split() 字符串分割
 4  * 不支持正则表达式
 5  * 
 6  * StringTokenizer(String str, String delim) 
 7 
 8  * @author Administrator
 9  *
10  */
11 public class Demo02 {
12 
13     /**
14      * @param args
15      */
16     public static void main(String[] args) {
17         String emailStr="bjq@163.com;bjq@qq.com;bjq@sohu.com";
18         StringTokenizer token =new StringTokenizer(emailStr,";");
19         //遍历获取
20         while(token.hasMoreElements()){
21             System.out.println(token.nextElement());
22         }
23     }
24 
25 }
示例代码

其它集合类

  WeakHashMap

    键为弱引用,回收键后自动删除key-value对象

  IdentityHashMap

    键只以地址去重,而不是比较hashCode与equals

    注意:键是常量池中的字符串

  EnumMap

    键必须为枚举的值

    构造器:public EnumMap (指定枚举类class对象)

 1 /**
 2  * WeakHashMap 键为弱类型,gc运行立即回收
 3  * @author Administrator
 4  *
 5  */
 6 public class WeakHashMapDemo {
 7 
 8     /**
 9      * @param args
10      */
11     public static void main(String[] args) {
12         WeakHashMap<String,String> map =new WeakHashMap<String,String>();
13         //测试数据
14         //常量池对象,不会回收
15         map.put("abc", "a");
16         map.put("d", "test");
17         //gc运行 已被回收
18         map.put(new String("bjsxt"), "c");
19         map.put(new String("dsf"), "d");
20         
21         //通知回收
22         System.gc();
23         System.runFinalization();
24         
25         System.out.println(map.size());
26     }
27 
28 }
29 
30 /**
31  * IdentityHashMap 键比较地址去重
32  * @author Administrator
33  *
34  */
35 public class IdentityHashMapDemo {
36 
37     /**
38      * @param args
39      */
40     public static void main(String[] args) {
41         IdentityHashMap<String ,String> map =new IdentityHashMap<String,String>();
42         //常量池中的"a"
43         map.put("a", "a1");
44         map.put("a", "a2");
45         System.out.println(map.size());
46         map.put(new String("a"), "a3");
47         map.put(new String("a"), "a4");
48         System.out.println(map.size());
49         
50     }
51 
52 }
53 
54 /**
55  * EnumMap要求键为枚举
56  * @author Administrator
57  *
58  */
59 public class EnumMapDemo {
60 
61     /**
62      * @param args
63      */
64     public static void main(String[] args) {
65         EnumMap<Season,String> map =new EnumMap<Season,String>(Season.class);
66         //存放值
67         map.put(Season.SPRING, "春困");
68         map.put(Season.SUMMER, "夏无力");
69         map.put(Season.AUTUMN, "秋乏");
70         map.put(Season.WINTER, "冬眠");
71         
72         System.out.println(map.size());
73         
74     }
75 
76 }
77 //季节
78 enum Season{
79     SPRING,SUMMER,AUTUMN,WINTER
80 }
示例代码

Collections

  • 专门用来操作集合的工具类
    • 构造方法私有,禁止创建对象
    • 提供一系列静态方法实现对各种集合的操作
    • 具体操作:搜索、复制、排序、线程安全化等
  • 常用方法
    • Collections.addAll(list, "aaa","bbb","ccc","ccc");
    • int index = Collections.binarySearch(list, "ccc");
    • Collections.copy(list2, list);
    • Collections.fill(list3, "888");
    • String max = Collections.max(list4);
    • String min = Collections.min(list4);
    • Collections.reverse(list4);
    • List list5 = Collections.synchronizedList(list4);

  • 同步控制:多线程并发访问集合的线程安全

     1. 常用容器ArrayList、HashSet、HashMap等都是线程不安全的

      2. Collection提供了synchronizedXxx()方法,将指定容器包装成同步

      synchronizedList()

      synchronizedSet()

      synchronizedMap()

 1 /**
 2  * 使用Collections管理同步 容器
 3  * synchronizedList()
 4     synchronizedSet()
 5     synchronizedMap()
 6 
 7  * @author Administrator
 8  *
 9  */
10 public class Demo01 {
11 
12     /**
13      * @param args
14      */
15     public static void main(String[] args) {
16         List<String> list =new ArrayList<String>();
17         list.add("a");
18         list.add("b");
19         //list可以同步
20         List<String> synList =Collections.synchronizedList(list);
21         System.out.println("线程安全的list制作完毕");
22     }
23 
24 }
View Code

  • 不可变设置:只读访问,Collection提供了三种方法

     1. emptyXxx() 空的不可变集合

      2. singletonXxx() 一个元素不可变的集合

      3. unmodifiableXxx() 不可变容器

 1 /**
 2  * 只读设置
 3  * 1、emptyXxx()  空的不可变的集合 
 4  *    emptyList() 
 5  *    emptyMap()
 6  *    emptySet()
 7  * 2、singletonXxx() 一个元素不可变的集合
 8  *    singleton(T o) 
 9  *    singletonList(T o) 
10  *    singletonMap(K key, V value) 
11  * 
12  * 3、unmodifiableXxx() 不可变容器
13  *    unmodifiableList(List<? extends T> list) 
14  *    unmodifiableSet(Set<? extends T> s) 
15  *    unmodifiableMap(Map<? extends K,? extends V> m) 
16  * @author Administrator
17  *
18  */
19 public class Demo02 {
20 
21     /**
22      * @param args
23      */
24     public static void main(String[] args) {
25         Map<String,String> map =new HashMap<String,String>();
26         
27         map.put("test", "test");
28         map.put("bjsxt", "bjsxt");
29         
30         //只读控制
31         Map<String,String> map2 =Collections.unmodifiableMap(map);
32         //map2.put("a", "a"); //不能操作
33         System.out.println(map2.size());
34         
35         //一个元素的容器测试
36         List<String> list =Collections.singletonList(new String());
37         list.add("test");
38         //list.add("bjsxt"); //只能包含一个元素的容器
39     }
40     
41     public static Set<String> oper(Set<String> set){
42         if(null==set){
43             return Collections.EMPTY_SET; //外部获取避免NullPointerException
44         }
45         //操作
46         return set;
47     }
48 
49 }
View Code

旧的集合类

  • Vector
    • 实现原理和ArrayList相同,功能相同,都是长度可变的数组结构,很多情况下可以互用
    • 两者的主要区别如下
      • Vector是早期JDK接口,ArrayList是替代Vector的新接口
      • Vector线程安全,效率低下;ArrayList重速度轻安全,线程非安全
      • 长度需增长时,Vector默认增长一倍,ArrayList增长50%
  • Hashtable类
    • 实现原理和HashMap相同,功能相同,底层都是哈希表结构,查询速度快,很多情况下可互用
    • 两者的主要区别如下
    • Hashtable是早期JDK提供的接口,HashMap是新版JDK提供的接口
    • Hashtable继承Dictionary类,HashMap继承AbstractMap类
    • Hashtable线程安全,HashMap线程非安全
    • Hashtable键值都不允许null值,HashMap键允许一个null值,值允许有多个null值

    • 子类Properties

      作用:读写资源配置文件

      要求键和值只能为字符串

      方法:

        setProperty(String key, String value)

        getProperty(String key)

        getProperty(String key, String defaultValue)

        load(InputStream inStream)

        load(Reader reader)

        loadFromXML(InputStream in)

        store(OutputStream out, String comments)

        store(Writer writer, String comments)

        storeToXML(OutputStream os, String comment)// 字符集默认UTF-8

        storeToXML(OutputStream os, String comment, String encoding)

      类路径加载文件

        1)类.class.getResourceAsStream("/com/others/pro/db.properties")

        2)Thread.currentThread().getContextClassLoader().getResourceAsStream("com/others/pro/db.properties")

 1 /**
 2  * 使用Properties 输出到文件
 3  * 资源配置文件:
 4  * 
 5  * 1、.properties
 6  * store(OutputStream out, String comments) 
 7     store(Writer writer, String comments) 
 8    2、.xml
 9    storeToXML(OutputStream os, String comment)  :UTF-8字符集
10    storeToXML(OutputStream os, String comment, String encoding) 
11     
12 
13  * @author Administrator
14  *
15  */
16 public class Demo01{
17 
18     /**
19      * @param args
20      * @throws IOException 
21      * @throws FileNotFoundException 
22      */
23     public static void main(String[] args) throws FileNotFoundException, IOException {
24         //创建对象
25         Properties pro =new Properties();
26         //存储
27         pro.setProperty("driver", "oracle.jdbc.driver.OracleDriver");
28         pro.setProperty("url", "jdbc:oracle:thin:@localhost:1521:orcl");
29         pro.setProperty("user", "scott");
30         pro.setProperty("pwd", "tiger");
31         
32         //存储到e:/others  绝对路径  盘符:
33         //pro.store(new FileOutputStream(new File("e:/others/db.properties")), "db配置");
34         //pro.storeToXML(new FileOutputStream(new File("e:/others/db.xml")), "db配置");
35         //使用相对路径 当前的工程
36 //        pro.store(new FileOutputStream(new File("db.properties")), "db配置");
37 //        pro.store(new FileOutputStream(new File("src/db.properties")), "db配置");
38         pro.store(new FileOutputStream(new File("src/com/bjsxt/others/pro/db.properties")), "db配置");
39     }
40 
41 }
42 
43 
44 /**
45  * 使用Properties读取配置文件
46  * 资源配置文件:
47  * 使用相对与绝对路径读取
48  * load(InputStream inStream) 
49    load(Reader reader) 
50    loadFromXML(InputStream in) 
51  * @author Administrator
52  *
53  */
54 public class Demo02 {
55 
56     /**
57      * @param args
58      * @throws IOException 
59      * @throws FileNotFoundException 
60      */
61     public static void main(String[] args) throws FileNotFoundException, IOException {
62         Properties pro=new Properties();
63         //读取 绝对路径
64         //pro.load(new FileReader("e:/others/db.properties"));
65         //读取 相对路径
66         pro.load(new FileReader("src/com/others/pro/db.properties"));
67         System.out.println(pro.getProperty("user", "uuu"));
68     }
69 }
70 
71 /**
72  * 使用类相对路径读取配置文件
73  *  bin  
74  * @author Administrator
75  *
76  */
77 public class Demo03 {
78 
79     /**
80      * @param args
81      * @throws IOException 
82      */
83     public static void main(String[] args) throws IOException {
84         Properties pro =new Properties();
85         //类相对路径的 / bin 
86         //pro.load(Demo04.class.getResourceAsStream("/com/others/pro/db.properties"));
87         //"" bin 
88         pro.load(Thread.currentThread().getContextClassLoader()
89             .getResourceAsStream("com/others/pro/db.properties"));
90         System.out.println(pro.getProperty("user", "uuu"));
91     }
92 
93 }
示例代码

新的线程同步集合类

  • 早期集合类Vector、Hashtable:线程安全的
    • 是怎么保证线程安排的,使用synchronized修饰方法
  • 为了提高性能,使用ArrayList、HashMap替换,线程不安全,但是性能好。使用ArrayList、
    HashMap,需要线程安全怎么办呢?
      • 使用Collections.synchronizedList(list);Collections.synchronizedMap(m);解决
      • 底层使用synchronized代码块锁
      • 虽然也是锁住了所有的代码,但是锁在方法里边,比锁在方法外边性能可以理解为稍有提高吧。毕竟进方法本身就要分配资源的
  • 在大量并发情况下如何提高集合的效率和安全呢?
    • 提供了新的线程同步集合类,位于java.util.concurrent包下,使用Lock锁
    • ConcurrentHashMap、CopyOnWriteArrayList 、CopyOnWriteArraySet:
    • 注意不是CopyOnWriteHashSet

集合总结

  • 集合和数组的比较
    • 数组不是面向对象的,存在明显的缺陷,集合完全弥补了数组的一些缺点,比数组更灵活更实用,可大大提高软件的开发效率而且不同的集合框架类可适用于不同场合。具体如下:
    • 1 : 数组容量固定且无法动态改变,集合类容量动态改变。
    • 2:数组能存放基本数据类型和引用数据类型的数据,而集合类中只能放引用数据类型的数据。
    • 3:数组无法判断其中实际存有多少元素,length只告诉了array容量;集合可以判断实际存有多少元素,而对总的容量不关心
    • 4:集合有多种数据结构(顺序表、链表、哈希表、树等)、多种特征(是否有序,是否唯一)、不同适用场合(查询快,便于删除、有序),不像数组仅采用顺序表方式
    • 5:集合以类的形式存在,具有封装、继承、多态等类的特性,通过简单的方法和属性调用即可实现各种复杂操作,大大提高软件的开发效率。

  • ArrayList和LinkedList 的联系和区别
    • 联系:
      • 都实现了List接口
      • 有序 不唯一(可重复)
    • ArrayList
      • 在内存中分配连续的空间,实现了长度可变的数组
      • 优点:遍历元素和随机访问元素的效率比较高
      • 缺点:添加和删除需大量移动元素效率低,按照内容查询效率低,
    • LinkedList
      • 采用链表存储方式。
      • 缺点:遍历和随机访问元素效率低下
      • 优点:插入、删除元素效率比较高(但是前提也是必须先低效率查询才可。如果插入删除发生在头尾可以减少查询次数)

  • Vector和ArrayList的联系和区别
    • 实现原理相同,功能相同,都是长度可变的数组结构,很多情况下可以互用
    • 两者的主要区别如下
      • Vector是早期JDK接口,ArrayList是替代Vector的新接口
      • Vector线程安全,效率低下;ArrayList重速度轻安全,线程非安全
      • 长度需增长时,Vector默认增长一倍,ArrayList增长50%

  • HashMap和Hashtable的联系和区别
    • 实现原理相同,功能相同,底层都是哈希表结构,查询速度快,在很多情况下可以互用
    • 两者的主要区别如下
      • Hashtable是早期JDK提供的接口,HashMap是新版JDK提供的接口
      • Hashtable继承Dictionary类,HashMap继承AbstractMap类
      • Hashtable线程安全,HashMap线程非安全
      • Hashtable键值都不允许null值,HashMap键允许一个null值,值允许有多个null值

  • Collection和Collections的区别
    • Collection是Java提供的集合接口,存储一组不唯一,无序的对象。它有两个子接口List和Set。
    • Java中还有一个Collections类,专门用来操作集合类 ,它提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。

 

 

posted @ 2018-05-30 00:38  jqbai  阅读(173)  评论(0)    收藏  举报