集合

1.集合框架的优点

传统的容器(数组)在进行增、删等破坏性操作时,需要移动元素,可能导致性能问题;同时添加、删除等算法和具体业务耦合在一起,增加了程序开发的复杂度。

Java集合框架提供了一套性能优良、使用方便的接口和类,它们位于java.util包中。

2.Collection

Collection是java集合框架(collection-frame)中的顶层接口。

Collection接口是一个容器,容器中只能存储引用数据类型,建议存同一类型的引用类型,方便后续遍历等操作。

容器中的元素可以是有序的、可重复的,称为List接口;也可能是无序的、唯一的,称为Set接口。

1).集合常用方法

 1 public static void main(String[] args) {
 2         
 3         /**
 4          * 增:add/addAll
 5          * 删:clear/remove/removeAll/retainAll
 6          * 改:
 7          * 查:contains/containsAll/isEmpty/size
 8          */
 9         
10         Collectionc1 = newArrayList();
11         
12         // 追加
13         c1.add("apple"); // Object object = new String("apple");
14         // c1.add(1);         // Object object = new Integer(1); 
15         c1.add("banana");
16         System.out.println(c1);
17         
18         // 追加一个集合
19         Collectionc2 = newArrayList();
20         c2.add("java");
21         c2.add("c++");
22         c1.addAll(c2);
23         System.out.println(c1);
24         
25         // clear
26         //c1.clear();
27         
28         // c1.remove("apple");
29         // c1.removeAll(c2);
30         //c1.retainAll(c2);
31         //System.out.println(c1);
32         
33         System.out.println(c1.contains("apple"));
34         c2.add("js");
35         System.out.println(c1.containsAll(c2));
36         // c1.clear();
37         System.out.println(c1.isEmpty());
38         // 返回集合元素的个数
39         System.out.println(c1.size());
40         
41         System.out.println(c1.equals(c2));
42         
43     }

2).集合的遍历

Iterable可遍历的接口,集合接口继承于它,集合支持快速遍历。

1 // 快速遍历
2         // for-each
3         // Object 表示元素类型
4         // item表示迭代变量
5         // c1表示集合
6         for (Object item : c1) {
7             System.out.println(item.toString());
8         }

快速遍历的本质:

Collection继承Iterable接口,表示集合支持快速遍历。Iterable接口定义了一个方法iterator()用于获取集合的迭代器,是一个Iterator接口类型,iterator()内部返回一个实现类实现类Iterator接口。这个实现类一定具有hasNext和next方法用于判断是否有下一个元素和获取下一个元素。快速遍历就是基于迭代器工作的。

迭代器遍历如下:

 1 public static void main(String[] args) {
 2         
 3 
 4         Collectionc1 = newArrayList();
 5         c1.add("apple");
 6         c1.add("banana");
 7         c1.add("coco");
 8         
 9         
10         // 快速遍历
11         // for-each
12         // Object 表示元素类型
13         // item表示迭代变量
14         // c1表示集合
15         for (Object item : c1) {
16             System.out.println(item.toString());
17         }
18         
19         // 迭代器遍历(国内)
20         Iteratorit = c1.iterator();
21         while(it.hasNext()) {
22             Object item = it.next();
23             System.out.println(item.toString());
24         }
25         
26         // 国外
27         for(Iteratorit2=c1.iterator();it2.hasNext();) {
28             Object item = it2.next();
29             System.out.println(item.toString());
30         }    
31     }

3.List接口

 

List 接口中的元素时有序的、可重复的。List接口中的元素通过索引(index)来确定元素的顺序。

有序的 collection(也称为序列)。可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素

1).List常用方法

 1 public static void main(String[] args) {
 2         
 3         /**
 4          * 增:add/addAll/add(index,el)/addAll(index,collection)
 5          * 删:clear/remove/removeAll/remove(index)
 6          * 改:set(index,el)
 7          * 查:get(index)/indexOf/lastIndexOf()
 8          * 其他:contains/containsAll/isEmpty/size
 9          */
10         Listlist1 = newArrayList();
11         // 添加元素
12         list1.add("apple");
13         list1.add("banana");
14         // 在指定位置添加元素
15         list1.add(0, "coco");
16         
17         System.out.println(list1);
18         
19         Listlist2 = newArrayList();
20         list2.add("java");
21         list2.add("c++");
22         
23         list1.addAll(1, list2);
24         System.out.println(list1);
25         
26         // 删除
27         list1.remove(0);
28         System.out.println(list1);
29         
30         // 修改
31         list1.set(0, "javax");
32         System.out.println(list1);
33         
34         //
35         System.out.println(list1.get(0));
36         list1.add("apple");
37         list1.add("apple");
38         System.out.println(list1);
39         System.out.println(list1.indexOf("apple"));
40         System.out.println(list1.lastIndexOf("apple"));
41     }

2).List接口遍历

 定义: ListIterator 继承于Iterator,在Iterator的基础上提供了以正向遍历集合,也可以以逆序遍历集合合。

——hasNext/next 以正向遍历

——hasPrevious/previous 以逆序遍历

 

 

 1 public static void main(String[] args) {
 2         
 3         
 4         List list1 = new ArrayList();
 5         list1.add("apple");
 6         list1.add("banana");
 7         list1.add("coco");
 8         
 9         // 【1】快速遍历
10         System.out.println("--for each--");
11         for (Object item : list1) {
12             System.out.println(item.toString());
13         }
14         
15         // 【2】普通for
16         System.out.println("--for--");
17         for(inti=0;i<list1.size();i++) {
18             System.out.println(list1.get(i));
19         }
20         
21         // 【3】集合迭代器
22         System.out.println("--iterator--");
23         Iterator it = list1.iterator();
24         while(it.hasNext()) {
25             System.out.println(it.next());
26         }
27         
28         System.out.println("--list iterator--");
29         // 正向遍历
30         ListIterator it2 = list1.listIterator();
31         while(it2.hasNext()) {
32             System.out.println(it2.next());
33         }
34         
35         // 逆序遍历
36         while(it2.hasPrevious()) {
37             System.out.println(it2.previous());
38         }
39         
40         System.out.println("--list iterator with index--");
41         ListIteratorit3 = list1.listIterator(1);
42         while(it3.hasNext()) {
43             System.out.println(it3.next());
44         }
45     }

4.数据结构

定义:数据结构就是数据在内存中存储结构。根据存储的方式不同,分为线性表、二叉树、图、栈、队列等

 1).线性表

线性表数据按照一定的逻辑顺序存储在内存中。线性表是有序的。

线性表根据内存的物理结构分为两种:数组和链表

[1].数组是一种逻辑上有序的线性表,物理上也连续。

[2].链表是一种逻辑上有序的线性表,但物理上不连续。

 

数组和链表的区别:

相同点:都是按照一定的逻辑顺序

不同点:数组在物理上是连续的,所以数组在查询时效率高,在添加、删除元素时效率低(涉及移素);

       而链表在物理上是不连续的,所以链表在查询时效率低(每次从头开始,不能跳跃访问),在添     加、删除元素时效率高(不涉及移动元素)

 2).栈

元素进出本质:先进后出,后进先出

3).队列

元素进出本质:先进先出,后进后出

5.ArrayList /Vector

——ArrayList 是List接口的实现类,底层数据结构是数组,实现大小可变的数组。

ArrayList线程不安全,jdk1.2

——ArrayList底层数据结构是数组,默认数组大小是10,如果添加的元素个数超过默认容量,ArrayList会自动拓容,拓容原则:newCapacity = oldCapacity+oldCapacity/2;如果未来确定序列的元素不在增加,通过调用trimToSize()调制容量至合适的空间。

——ArrayList作为List接口的实现类,常用方法和遍历方法参考List接口。

——Vector是List接口的实现类,底层数据结构也是数组,也是大小可变的数组。

Vector是线程安全的,jdk1.0

——Vector底层数据结构是数组,默认数组大小是10,如果添加的元素个数超过默认容量,Vector会自动拓容,拓容原则:newCapacity = oldCapacity +capacityIncrement(增长因子);如果未来确定序列的元素不在增加,通过调用trimToSize()调制容量至合适的空间。

——注:Vector 在实现List接口的同时,同添加了自身特有的方法xxxElement,未来使用时为了程序的可拓展性,一定要按照接口来操作Vector。

6.LinkedList

LinkedList是List接口的实现类,底层数据结构是链表。

LinekList常用方法和遍历方法参照List接口。

LinkedList 线程不安全,没有相对应的线程安全的接口,有以下方法:

线程安全语法:List list = Collections.synchronizedList(new LinkedList(...));

除了实现List接口,还实现栈接口,队列接口,双向队列接口

 1).栈接口

push入栈操作/pop出栈操作

 1 public class Test01 {
 2     public static void main(String[] args) {
 3         LinkedList list = new LinkedList();
 4         list.push("apple");
 5         list.push("banana");
 6         list.push("coco");
 7         
 8         
 9         System.out.println(list.pop());
10         System.out.println(list.pop());
11         System.out.println(list.pop());
12         
13         // java.util.NoSuchElementException
14         System.out.println(list.pop());
15     }
16 }

2).队列(Queue)接口

 

add/remove/element() 可能会出现NoSuchElementException异常

 1 public static void main(String[] args) {
 2         
 3         LinkedListqueue = newLinkedList();
 4         // 入队
 5         /**
 6          * 队列头        队列尾
 7          *<-----          <-----
 8          * [apple, banana, coco]
 9          */
10         queue.add("apple");
11         queue.add("banana");
12         queue.add("coco");
13         System.out.println(queue);
14         
15         // 出队
16         System.out.println(queue.remove());
17         System.out.println(queue.remove());
18         System.out.println(queue.remove());        
19         System.out.println(queue);
20         
21         // java.util.NoSuchElementException
22         System.out.println(queue.remove());
23         
24         
25         // 获取表头元素
26         System.out.println(queue.element());
27     }

offer/poll/peek 可能会返回特殊值(null)

 1 public static void main(String[] args) {
 2         
 3         LinkedListqueue = newLinkedList();
 4         // 入队
 5         /**
 6          * 队列头        队列尾
 7          *<-----          <-----
 8          * [apple, banana, coco]
 9          */
10         queue.offer("apple");
11         queue.offer("banana");
12         queue.offer("coco");
13         
14         // 出队列
15         //System.out.println(queue.poll());
16         //System.out.println(queue.poll());
17         //System.out.println(queue.poll());
18         System.out.println(queue);
19 
20         //System.out.println(queue.poll());
21         
22         // 获取表头元素
23         System.out.println(queue.peek());
24     
25     }

3).双向队列(Deque)接口

 1 /**
 2  * 以双向队列形式操作LinkedList
 3  */
 4 public class Test04 {
 5     publicstaticvoid main(String[] args) {
 6         
 7         LinkedListqueue = newLinkedList();
 8         // 入队
 9         /**
10          *<-----          <-----
11          * [apple, banana, coco]
12          * ---->           ----->
13          */
14         
15         queue.addFirst("apple");
16         queue.addFirst("banana");
17         queue.addFirst("coco");
18         System.out.println(queue);
19         
20         System.out.println(queue.removeLast());
21         System.out.println(queue.removeFirst());
22         System.out.println(queue.removeFirst());
23         System.out.println(queue);
24         
25         // 获取头元素
26         System.out.println(queue.getFirst());
27     
28     }
29 }

7.Iterator和ListIterator

  1).Iterator在迭代过程中不允许向集合中添加元素

 1 public static void main(String[] args) {
 2         ArrayList list = new ArrayList();
 3         list.add("apple");
 4         list.add("banana");
 5         list.add("coco");
 6         
 7         Iteratorit = list.iterator();
 8         while(it.hasNext()) {
 9             String item = (String) it.next();
10             if(item.equals("banana")) {
11                 list.add("test");
12             }
13         }
14         
15         System.out.println(list);
16     }

当通过Iterator集合迭代器遍历集合过程中,不能再向集合汇总添加元素,否则出现ConcurrentModificationException并发修改异常。

 

2).ListIterator允许程序员按任一方向遍历列表、迭代期间修改列表,并获得迭代器在列表中的当前位置

 1 publicclass Test01 {
 2     public static void main(String[] args) {
 3         ArrayListlist = newArrayList();
 4         list.add("apple");
 5         list.add("banana");
 6         list.add("coco");
 7         
 8         ListIteratorit = list.listIterator();
 9         while(it.hasNext()) {
10             String item = (String) it.next();
11             if(item.equals("banana")) {
12                 it.add("test");
13             }
14         }
15         
16         System.out.println(list);
17     }
18 }

注:为了更加了解以上可以去熟悉Iterator实现类的源码hasNext/next

 8.泛型(generic)

1).泛型的概念

 

泛型允许开发者在强类型程序设计语言(java)编写代码时定义一些可变部分,这些部分在使用前必须作出指明。

 

泛型本质就是将类型参数化

——ArrayList<E>  list表示声明了一个列表list,列表的元素是E类型

 

——ArrayList<String> list = new ArrayList<String>();

       声明了一个列表list,列表的元素只能是String类型。

 

 2).泛型的擦除

 注意:泛型在编译器起作用,运行时jvm察觉不到泛型的存在。(泛型在运行过程中被擦除了)

1 public static void main(String[] args) {
2         ArrayList<String>list = new ArrayList<String>();
3         list.add("apple");
4         System.out.println(listinstanceof ArrayList);
5         System.out.println(listinstanceof ArrayList<String>);//抛出异常
      System.out.println(listinstanceof ArrayList<?>);//正确
6 }

会抛出异常:Cannot perform instanceof check against parameterized type ArrayList<String>. Use the form ArrayList<?> instead since further generic type information will be erased at runtime

 

3).泛型的应用

[1].泛型类

当一个类中属性的数据类型不确定时,具体是什么类型由使用者来确定时,使用泛型。

泛型类的形式

public class 类名<T>{

}

定义一个泛型类

 1 public class FanClass<T> {
 2     private T t;
 3 
 4     public T getT() {
 5         returnt;
 6     }
 7 
 8     publicvoid setT(T t) {
 9         this.t = t;
10     }
11 
12     public FanClass(T t) {
13         super();
14         this.t = t;
15     }
16 
17     public FanClass() {
18         super();
19     }
20 }
1 public class Test01 {
2     publicstaticvoid main(String[] args) {
3         FanClass<String>fan = new FanClass<String>();
4         fan.setT("apple");
5         
6         FanClass<Integer>fan2 = new FanClass<Integer>();
7         fan2.setT(1);
8     }
9 }

[2].泛型方法

当一个方法的参数类型不确定时,具体是什么类型由使用者来确定,可以考虑使用泛型方法。

形式如下:

public<T> void xxx(T a) {
    System.out.println(a);
}

定义一个泛型的方法:

 1 public class Student {
 2     
 3     
 4     /*public void showInfo(int a) {
 5         System.out.println(a);
 6     }
 7     
 8     public void showInfo(float a) {
 9         System.out.println(a);
10     }
11     
12     public void showInfo(String a) {
13         System.out.println(a);
14     }*/
15     
16     public<T>void showInfo(Ta) {
17         System.out.println(a);
18     }
19 }
public static void main(String[] args) {
        
        Student stu = new Student();  
        stu.showInfo(1);
        stu.showInfo("apple");
        stu.showInfo(1.0f);
    }

注:泛型方法在调用时确定(指明)类型。

——泛型方法在一定程度上优化了方法重载。

   泛型方法可以定义多个泛型类型

// 可以定义多个泛型的类型
    public<A,B>void showInfo(Aa,B b) {
        System.out.println(a);
        System.out.println(b);
    }

注:多个泛型类型进一步优化了方法重载。

多个同类型的泛型

 1 // 多个同类型的泛型
 2     /*public <A> void print(A a) {
 3         System.out.println(a);
 4     }
 5     public <A> void print(A a,A b) {
 6         System.out.println(a);
 7         System.out.println(b);
 8     }*/
 9     
10     public<A>void print(A...a) {
11         System.out.println(a);
12     }

A… a 表示方法可以接受多个参数。当调用方法传递多个参数时,多个参数被放到a数组中,a是什么类型的数组由开发者调用处传参决定。

stu.print(1);
stu.print(1,2);           
stu.print("apple");
stu.print("apple","banana");

print(A...a)方法称为可变参数的泛型形式。

  4) 泛型接口

如果接口中的方法的参数(形参、返回值)不确定时,可以考虑使用泛型接口。形式

public interface FanInterface<T> {

    public void showInfo(T t);

}

[1]实现类能确定泛型接口的类型

publicclass ImplClass implements FanInterface<String>{

     @Override

     publicvoid showInfo(Stringt) {

         // TODO Auto-generated method stub
     }
}

[2]实现类不能确定泛型接口的类型->继续泛。

public class ImplClass2<T>implements FanInterface<T>{
 
     @Override

     publicvoid showInfo(T t) {

     }

}

5) 泛型的上限和下限

public static void print(ArrayList<? extendsPet>list) {

        for (Petpet : list) {

            pet.showInfo();
        }
    }

泛型的上限ArrayList(? extends Pet) list 声明了一个容器,容器中的元素类型一定要继承于Pet,我们称这种形式叫做泛型的上限。

泛型的下限ArrayList(? super Pet) list 声明了一个容器,容器中的元素类型一定要是Pet的父类,我们称这个形式为泛型的下限。

9. Set接口

Set接口表示一个唯一、无序的容器(和添加顺序无关)

 1).Set接口提供的方法

 1 public static void main(String[] args) {
 2 
 3          /**
 4 
 5           * 增:add/addAll
 6 
 7           * 删:clear/remove/removeAll/retainAll
 8 
 9           * 改:
10 
11           * 查:contains/containsAll
12 
13           * 遍历:iterator
14 
15           * 其他:size/isEmpty
16 
17           */
18 
19         
20 
21          Set<Integer>set = new HashSet<Integer>();
22 
23          // [1]添加
24 
25          // 无序
26 
27           set.add(10);
28 
29          set.add(3);
30 
31          set.add(20);
32 
33          set.add(0);
34 
35          // 不能添加重复元素
36 
37          booleanr = set.add(1);
38 
39          System.out.println(set);
40 
41         
42 
43          // 【2】删除
44 
45 //       set.remove(1);
46 
47 //       set.clear();
48 
49 //       System.out.println(set);
50 
51         
52 
53          // 【3】查看是否包含
54 
55          System.out.println(set.contains(1));
56 
57         
58 
59          // 【4】其他
60 
61          System.out.println(set.size());
62 
63          System.out.println(set.isEmpty());
64 
65      }

2)Set接口的遍历

public static void main(String[] args) {

        

         Set<String>set = new HashSet<String>();

         set.add("banana");

         set.add("apple");

         set.add("coco");


         // 快速遍历

         for (String item : set) {

              System.out.println(item);

         }

        
         // 迭代器

         Iterator<String>it = set.iterator();

         while(it.hasNext()) {

              String item = it.next();

              System.out.println(item);

         }

     }

Set接口的实现类常见的有HashSet、LinkedHashSet、TreeSet

 

10. HashSet

HashSet是Set接口的实现类,底层数据结构是哈希表。

HashSet是线程不安全的(不保证同步)

1) 哈希表工作原理

 

 

2)   添加自定义对象

根据哈希表的工作原理,请存储一个自定义对象到HashSet中。

 1 package cn.sxt03.hashset;
 2 
 3  
 4 
 5 public class Student {
 6 
 7      private String id;
 8 
 9      private String name;
10 
11      privateintage;
12 
13  
14 
15      //
16 
17     
18 
19  
20 
21      @Override
22 
23      publicinthashCode() {
24 
25          finalintprime = 31;
26 
27          intresult = 1;
28 
29          result = prime * result + age;
30 
31          result = prime * result + ((id == null) ? 0 : id.hashCode());
32 
33          result = prime * result + ((name == null) ? 0 : name.hashCode());
34 
35          returnresult;
36 
37      }
38 
39  
40 
41      @Override
42 
43      publicbooleanequals(Object obj) {
44 
45          if (this == obj)
46 
47               returntrue;
48 
49          if (obj == null)
50 
51               returnfalse;
52 
53          if (getClass() != obj.getClass())
54 
55               returnfalse;
56 
57          Student other = (Student) obj;
58 
59          if (age != other.age)
60 
61               returnfalse;
62 
63          if (id == null) {
64 
65               if (other.id != null)
66 
67                    returnfalse;
68 
69          } elseif (!id.equals(other.id))
70 
71               returnfalse;
72 
73          if (name == null) {
74 
75               if (other.name != null)
76 
77                    returnfalse;
78 
79          } elseif (!name.equals(other.name))
80 
81               returnfalse;
82 
83          returntrue;
84 
85      }
86 
87  
88 
89      @Override
90 
91      public String toString() {
92 
93          return"Student [id=" + id + ", name=" + name + ", age=" + age + "]";
94 
95      }
96 
97  
98 
99 }

总结

[1]如果向HashSet中存储元素时,元素一定要实现hashCode方法和equals方法。

[2]优点:添加、删除、查询效率高;缺点:无序

11.LinkedHashSet

LinkedHashSet是Set接口的实现类,底层数据结构哈希表+链表

哈希表用于散列元素;链表用于维持添加顺序。

如果要添加自定义对象元素,也需要重写hashCode和equals方法。

12.  TreeSet

TreeSet 是Set接口的实现类,底层数据结构是二叉树。

TreeSet存储的数据按照一定的规则存储。存储规则让数据表现出自然顺序。

1) TreeSet工作原理

 

 

 

——添加一个新元素t的存储的步骤

[1]如果集合无元素,t直接加入;如果集合有元素,t和根节点比较;

[2] 如果t小于根节点;把t放到根节点的左子树上;重复1-3步骤

[3]t大于根节点;把t放到根节点的右子树上;重复1-3步骤

 ——输出时按照一定的规则:左子树->根节点->右子树

 

2)内部比较器和外部比较器

根据TreeSet的工作原理,向TreeSet添加自定义元素?

向TreeSet中添加元素时,一定要提供比较策略,否则会出现ClassCastException。

比较策略分两种:内部比较器和外部比较器

 

  [1]     内部比较器

当一个自定义对象实现Comparable并实现compareTo方法时,通过指定具体的比较策略,此时称为内部比较器。

 1 package cn.sxt05.treeset;
 2 
 3  
 4 
 5 public class Student implements Comparable<Student>{
 6 
 7     private String id;
 8 
 9     private String name;
10 
11     privateintage;
12 
13  
14 
15     // 。。。
16 
17  
18 
19     @Override
20 
21     public String toString() {
22 
23         return"Student [id=" + id + ", name=" + name + ", age=" + age + "]";
24 
25     }
26 
27  
28 
29     @Override
30 
31     publicintcompareTo(Student o) {
32 
33         if(this.getAge()<o.getAge()) {
34 
35             return -1;
36 
37         }elseif(this.getAge() == o.getAge()) {
38 
39             return 0;
40 
41         }else {
42 
43             return 1;
44 
45         }
46 
47     }
48
49 }

比较策略的几种情况

—1—比较策略一般当前对象写在前面,待比较对象也在后面,比较结果默认升序

returnthis.getAge() - o.getAge() ;

如果想要降序,改变两个比较对象的位置即可。

—2—-多种比较因素

 1    @Override
 2 
 3      public int compareTo(Student o) {
 4 
 5          /*if(this.getAge()<o.getAge()) {
 6 
 7               return -1;
 8 
 9          }else if(this.getAge() == o.getAge()) {
10 
11               return 0;
12 
13          }else {
14 
15               return 1;
16 
17          }*/
18 
19         
20          // return  this.getAge() - o.getAge() ;
21 
22          if(this.getAge()<o.getAge()) {
23 
24               return -1;
25 
26          }elseif(this.getAge() == o.getAge()) {
27 
28               returnthis.getName().compareTo(o.getName());
29 
30          }else {
31 
32               return 1;
33 
34          }
35 
36      }

[2] 外部比较器

当实际开发过程中不知道添加元素的源代码、无权修改别人的代码,此时可以使用外部比较器。

Comparator位于java.util包中,定义了compare(o1,o2) 用于提供外部比较策略。

TreeSet接受一个指定比较策略的构造方法,这些比较策略的实现类必须实现Comparator

接口。

需求:按照字符串的长度比较

 1 publicclass Test01 {
 2 
 3     public static void main(String[] args) {
 4 
 5        
 6 
 7         LenComparator lenComparator = new LenComparator();
 8 
 9         TreeSet<String>set2 = new TreeSet<String>(lenComparator);
10 
11        
12 
13         set2.add("banana");
14 
15         set2.add("coco");
16 
17         set2.add("apple");
18 
19        
20 
21         set2.add("apple");
22 
23         System.out.println(set2);
24     
25 
26     }
27 
28 }
29 
30 class LenComparator implements Comparator<String>{
31 
32 
33     @Override
34 
35     publicint compare(String o1, String o2) {
36 
37         returno1.length() - o2.length();
38 
39     }  
40 
41 }

使用匿名内部类优化

 1 publicclass Test02 {
 2 
 3      public static void main(String[] args) {
 4   
 5 
 6          TreeSet<String>set2 = newTreeSet<String>(new Comparator<String>() {
 7 
 8  
 9 
10               @Override
11 
12               public int compare(String o1, String o2) {
13 
14                    returno1.length() - o2.length();
15 
16               }
17 
18              
19 
20          });
21 
22          set2.add("banana");
23 
24          set2.add("coco");
25 
26          set2.add("apple");
27 
28 
29          set2.add("apple");
30 
31          System.out.println(set2);
32 
33         
34 
35      }
36 
37 }

13.  Map接口

Map接口称为键值对集合或者映射集合,其中的元素(entry)是以键值对(key-value)的形式存在。

Map容器接口中提供了增、删、改、查的方式对集合进行操作。

Map接口中都是通过key来操作键值对,一般key是已知。通过key获取value。

1)  map常用方法

 1 public static void main(String[] args) {
 2 
 3         
 4 
 5          /**
 6 
 7           * 增:put/putAll
 8 
 9           * 删:clear/remove
10 
11           * 改:put
12 
13           * 查:get/containsKey/containsValue
14 
15           * 其他:isEmpty/size
16 
17           */
18 
19 
20          Map<String, String>map = new HashMap<String,String>();
21 
22         
23 
24          // 【1】put
25 
26          map.put("A", "apple");
27 
28          map.put("B", "banana");
29 
30          map.put("C", "coco");
31 
32         
33 
34          // 【2】删除
35 
36          // map.clear();
37 
38          // smap.remove("A");
39 
40         
41 
42          // 【3】修改
43 
44          //map.put("A", "apple x");
45 
46         
47 
48           // 【4】查看
49 
50          String val = map.get("A");
51 
52          System.out.println(map.containsKey("D"));
53 
54         
55          System.out.println(map);
56 
57      }

2). map接口的遍历

 通过keySet() 返回map中键的set集合。

 1 public static void main(String[] args) {
 2 
 3  
 4 
 5          Map<String, String>map = new HashMap<String,String>();
 6 
 7         
 8 
 9          map.put("B", "banana");
10 
11          map.put("A", "apple");
12 
13          map.put("C", "coco");
14 
15          // map无序
16 
17          // 可以根据key的自然顺序让map有序  =>一般用string作为key
18 
19          System.out.println(map);
20 
21         
22 
23         
24 
25          // 遍历
26 
27          Set<String>keys = map.keySet();
28 
29          for (String key : keys) {
30 
31               System.out.println(key+"=>"+map.get(key));
32 
33          }
34 
35         
36 
37          Iterator<String>it = keys.iterator();
38 
39          while(it.hasNext()) {
40 
41               String key = it.next();
42 
43               System.out.println(key+"=>"+map.get(key));
44 
45          }
46 
47      }

 

map中以键值对作为元素,键值对在map中称为entry,entrySet返回键值对的set集合。

 1 publicstaticvoid main(String[] args) {
 2 
 3  
 4 
 5          Map<String, String>map = new HashMap<String,String>();
 6 
 7         
 8 
 9          map.put("B", "banana");
10 
11          map.put("A", "apple");
12 
13          map.put("C", "coco");
14 
15          // map无序
16 
17          // 可以根据key的自然顺序让map有序  =>一般用string作为key
18 
19          System.out.println(map);
20 
21         
22 
23          // entrySet
24 
25          Set<Entry<String, String>>entrySet = map.entrySet();
26 
27          for (Entry<String, String>entry : entrySet) {
28 
29               System.out.println(entry.getKey()+"=>"+entry.getValue());
30 
31          }
32 
33         
34 
35          Iterator<Entry<String, String>>it2 = entrySet.iterator();
36 
37          while(it2.hasNext()) {
38 
39               Entry<String, String>entry = it2.next();
40 
41               System.out.println(entry.getKey()+"=>"+entry.getValue());
42 
43          }
44 
45      }

 

Map接口的实现类HashMap、LinkedHashMap、TreeMap

 14.   HashMap

HashMap是Map的实现类,key以HashSet存储。

HashMap是线程不安全的  jdk1.2,Hashtable是HashMap的线程安全版本。Jdk1.0

 1 public static void main(String[] args) {
 2 
 3         
 4 
 5          /*
 6 
 7          HashMap<String, Object> map = new HashMap<String,Object>();
 8 
 9         
10 
11          ArrayList<String> list1 = new ArrayList<String>();
12 
13          list1.add("alex");
14 
15          list1.add("alice");
16 
17          list1.add("allen");
18 
19          map.put("A", list1);
20 
21         
22 
23         
24 
25          ArrayList<String> list2 = new ArrayList<String>();
26 
27          list2.add("ben");
28 
29          list2.add("bill");
30 
31          map.put("B", list2);
32 
33         
34 
35          System.out.println(map);
36 
37          */
38 
39         
40 
41         
42 
43          HashMap<Student, Object>map = new HashMap<Student,Object>();
44 
45         
46 
47          ArrayList<String>list1 = new ArrayList<String>();
48 
49          list1.add("alex");
50 
51          list1.add("alice");
52 
53          list1.add("allen");
54 
55          Students1 = newStudent("001", "大狗", 20);
56 
57          map.put(s1, list1);
58 
59         
60 
61         
62 
63          ArrayList<String>list2 = new ArrayList<String>();
64 
65          list2.add("ben");
66 
67          list2.add("bill");
68 
69          Students2 = newStudent("001", "大狗", 20);
70 
71          // 修改
72 
73          map.put(s2, list2);
74 
75          System.out.println(map);
76 
77         
78 
79      }

总结:

[1]向HashMap中存储元素时,key一定要实现hashCode和equals.

[2]一般建议使用String作为Map接口的key

 

15.LinkedHashMap

LinkedHashMap是Map接口的实现类,key以LinkedHashSet存储。

哈希表散列key,链表维持key的添加顺序。

 

 1 public static void main(String[] args) {
 2 
 3         
 4 
 5         
 6 
 7          /*LinkedHashMap<String, Object> map = new LinkedHashMap<String,Object>();
 8 
 9         
10 
11          ArrayList<String> list2 = new ArrayList<String>();
12 
13          list2.add("ben");
14 
15          list2.add("bill");
16 
17          map.put("B", list2);
18 
19         
20 
21          ArrayList<String> list1 = new ArrayList<String>();
22 
23          list1.add("alex");
24 
25          list1.add("alice");
26 
27          list1.add("allen");
28 
29          map.put("A", list1);
30 
31         
32 
33          System.out.println(map);*/
34 
35         
36 
37         
38 
39         
40 
41          HashMap<Student, Object>map = new HashMap<Student,Object>();
42 
43         
44 
45          ArrayList<String>list1 = new ArrayList<String>();
46 
47          list1.add("alex");
48 
49          list1.add("alice");
50 
51          list1.add("allen");
52 
53          Student s1 = new Student("001", "大狗", 20);
54 
55          map.put(s1, list1);
56 
57         
58 
59          ArrayList<String>list2 = new ArrayList<String>();
60 
61          list2.add("ben");
62 
63          list2.add("bill");
64 
65          Student s2 = new Student("001", "大狗", 20);
66 
67          // 修改
68 
69          map.put(s2, list2);
70 
71          System.out.println(map);
72 
73         
74 
75      }

16.TreeMap

TreeMap是Map的实现类,key以TreeSet存储。

 1 public static void main(String[] args) {
 2 
 3         
 4 
 5         
 6 
 7          /*TreeMap<String, Object> map = new TreeMap<String,Object>(new Comparator<String>() {
 8 
 9  
10 
11               @Override
12 
13               public int compare(String o1, String o2) {
14 
15                    return o1.length() - o2.length();
16 
17               }
18 
19          });
20 
21         
22 
23          ArrayList<String> list2 = new ArrayList<String>();
24 
25          list2.add("ben");
26 
27          list2.add("bill");
28 
29          map.put("Aa", list2);
30 
31         
32 
33          ArrayList<String> list1 = new ArrayList<String>();
34 
35          list1.add("alex");
36 
37          list1.add("alice");
38 
39          list1.add("allen");
40 
41          map.put("B", list1);
42 
43         
44 
45          System.out.println(map);*/
46 
47         
48 
49          TreeMap<Student, Object>map = new TreeMap<Student,Object>(new Comparator<Student>() {
50 
51  
52 
53               @Override
54 
55               publicint compare(Student o1, Student o2) {
56 
57                    returno1.getAge() - o2.getAge();
58 
59               }
60 
61          });
62 
63          ArrayList<String>list1 = new ArrayList<String>();
64 
65          list1.add("alex");
66 
67          list1.add("alice");
68 
69          list1.add("allen");
70 
71          Student s1 = new Student("001", "大狗", 20);
72 
73          map.put(s1, list1);
74   
75 
76          ArrayList<String>list2 = new ArrayList<String>();
77 
78          list2.add("ben");
79 
80          list2.add("bill");
81 
82          Student s2 = new Student("001", "2狗", 20);
83 
84          // 修改
85 
86          map.put(s2, list2);
87 
88          System.out.println(map);
89 
90         
91 
92      }

17.总结

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2019-04-30 19:55  他也就火三年  阅读(220)  评论(0编辑  收藏  举报