zoukankan      html  css  js  c++  java
  • 集合

    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.总结

  • 相关阅读:
    关键字与标识符
    JAVA 程序的基本语法
    第一个java程序中文乱码以及如何解决
    第一个java程序以及java的运行机制
    java中求余%与取模floorMod的区别
    Volley 框架解析(二)--RequestQueue核心解读
    Volley 源码解析
    Android之Activity系列总结(三)--Activity的四种启动模式
    Android之Activity系列总结(二)--任务和返回栈
    Android之Activity系列总结(一)--Activity概览
  • 原文地址:https://www.cnblogs.com/qq2267711589/p/10797837.html
Copyright © 2011-2022 走看看