zoukankan      html  css  js  c++  java
  • Collection与Map容器

    1.Collection接口

    Collection 是java集合框架的顶层接口,它表示为容器,只能存储应用类型数据,为了方便后续遍历最后存储同一类型数据。

    Collection 有增删改查等方法。

     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         Collection c1 = new ArrayList();
    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         Collection c2 = new ArrayList();
    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     }

     集合的遍历

    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         Collection c1 = new ArrayList();
     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         Iterator it = c1.iterator();
    21         while(it.hasNext()) {
    22             Object item = it.next();
    23             System.out.println(item.toString());
    24         }
    25         
    26         // 国外
    27         for(Iterator it2=c1.iterator();it2.hasNext();) {
    28             Object item = it2.next();
    29             System.out.println(item.toString());
    30         }    
    31     }

    Collection 有两个子接口分别为Set 和 List

    Set 接口是无序的、唯一的;List接口是有序的、不唯一的。

    List 接口

    1.1.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         List list1 = new ArrayList();
    11         // 添加元素
    12         list1.add("apple");
    13         list1.add("banana");
    14         // 在指定位置添加元素
    15         list1.add(0, "coco");
    16         
    17         System.out.println(list1);
    18         
    19         List list2 = new ArrayList();
    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     }

    1.1.1 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(int i=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         ListIterator it3 = list1.listIterator(1);
    42         while(it3.hasNext()) {
    43             System.out.println(it3.next());
    44         }
    45     }

    因Link 接口继承于Collection接口,所以拥有增删改查方法且自身拥有一些特殊方法。

    Link接口有三个重要的实现类:ArrayLink、vector、LinkedList

    ArrayLink

    ArrayLink的底层数据结构是数组,

    默认数组大小是10,如果添加的元素个数超过默认容量,ArrayList会自动拓容,拓容原则:newCapacity = oldCapacity + oldCapacity / 2;

    如果未来确定序列的元素不在增加,通过调用trimToSize()调制容量至合适的空间。

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

    优点:使用索引查询效率高,添加有序。缺点:删除、增加数据效率低

    Vector

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

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

    Vector跟ArrayLink基本一样;区别在于Vector是线程安全的,ArrayLink线程不安全。

    LinkedList

    LinkedList的底层数据结构是链表,优点:增删效率高,添加有序;缺点:查询效率低,线程是不安全的。

    除了实现List接口, 还实现栈接口

    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 }

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

     1 public static void main(String[] args) {
     2         
     3         LinkedList queue = new LinkedList();
     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     }

    Set接口

    因Set 接口继承于Collection接口,所以拥有增删改查方法且自身拥有一些特殊方法

    Set接口的三个实现类分别是:HarhSet、LinkedHarhSet、TreeSet

    HarhSet

    HarhSet的底层数据结构是哈希表,优点:增删查效率高;缺点:无序

    LinkedHarhSet

    LinkedHarhSet底层数据结构是链表+哈希表;优点:增删改效率高,添加有序;

    TreeSet

    TreeSet 底层数据结构是二叉树;唯一的,增删查效率中等,存储的数据按照一定的规则存储;存储规则让数据表现出自然顺序。

    2.泛型(generic)

    概念:

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

    泛型就是将类型参数化

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

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

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

    泛型在编译器起作用,运行时jvm察觉不到泛型的存在。

     泛型的擦除

    泛型在运行时已经被擦除了。

    1 public static void main(String[] args) {
    2         ArrayList<String> list = new ArrayList<String>();
    3         list.add("apple");
    4         System.out.println(list instanceof ArrayList);
    5         System.out.println(list instanceof ArrayList<String>);
    6 }
    7 Cannot perform instanceof check against parameterized type ArrayList<String>. Use the form ArrayList<?> instead since further generic type information will be erased at runtime

    泛型应用

     泛型类

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

    定义一个泛型类

     1 public class FanClass<T> {
     2     private T t;
     3 
     4     public T getT() {
     5         return t;
     6     }
     7 
     8     public void 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 }
    21 
    22 public class Test01 {
    23     public static void main(String[] args) {
    24         FanClass<String> fan = new FanClass<String>();
    25         fan.setT("apple");
    26         
    27         FanClass<Integer> fan2 = new FanClass<Integer>();
    28         fan2.setT(1);
    29     }
    30 }

    泛型方法

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

     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(T a) {
    17         System.out.println(a);
    18     }
    19 }
    20 
    21 public static void main(String[] args) {
    22         
    23         Student stu = new Student();
    24         stu.showInfo(1);
    25         stu.showInfo("apple");
    26         stu.showInfo(1.0f);
    27     }

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

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

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

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

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

    多个同类型的泛型

     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是什么类型的数组由开发者调用处传参决定。

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

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

    1.1.1 泛型接口C)

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

    1 public interface FanInterface<T> {
    2     public void showInfo(T t);
    3 }

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

    1 public class ImplClass implements FanInterface<String>{
    2 
    3     @Override
    4     public void showInfo(String t) {
    5         // TODO Auto-generated method stub
    6         
    7     }
    8 }

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

    1 public class ImplClass2<T> implements FanInterface<T>{
    2 
    3     @Override
    4     public void showInfo(T t) {
    5         
    6     }
    7 }

    1.1.1.1 泛型的上限和下限 (C)

    1 public static void print(ArrayList<? extends Pet> list) {
    2         for (Pet pet : list) {
    3             pet.showInfo();
    4         }
    5     }

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

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

    3.Map接口

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

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

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

    Map接口的三个重要实现类:TreeMap LinkHashMap HashMap

    TreeMap

    TreeMap底层数据结构为二叉树;keyTreeSet(二叉树)存储。

     1 public static void main(String[] args) {
     2         
     3         
     4         /*TreeMap<String, Object> map = new TreeMap<String,Object>(new Comparator<String>() {
     5 
     6             @Override
     7             public int compare(String o1, String o2) {
     8                 return o1.length() - o2.length();
     9             }
    10         });
    11         
    12         ArrayList<String> list2 = new ArrayList<String>();
    13         list2.add("ben");
    14         list2.add("bill");
    15         map.put("Aa", list2);
    16         
    17         ArrayList<String> list1 = new ArrayList<String>();
    18         list1.add("alex");
    19         list1.add("alice");
    20         list1.add("allen");
    21         map.put("B", list1);
    22         
    23         System.out.println(map);*/
    24         
    25         
    26         
    27         TreeMap<Student, Object> map = new TreeMap<Student,Object>(new Comparator<Student>() {
    28 
    29             @Override
    30             public int compare(Student o1, Student o2) {
    31                 return o1.getAge() - o2.getAge();
    32             }
    33         });
    34         
    35         ArrayList<String> list1 = new ArrayList<String>();
    36         list1.add("alex");
    37         list1.add("alice");
    38         list1.add("allen");
    39         Student s1 = new Student("001", "大狗", 20);
    40         map.put(s1, list1);
    41         
    42         
    43         ArrayList<String> list2 = new ArrayList<String>();
    44         list2.add("ben");
    45         list2.add("bill");
    46         Student s2 = new Student("001", "2狗", 20);
    47         // 修改
    48         map.put(s2, list2);
    49         System.out.println(map);
    50         
    51     }

    LinkHashMap

    LinkHashMap底层数据结构为链表+哈希表;key以LinkedHashSet存储。哈希表散列key,链表维持key的添加顺序。

     1 public static void main(String[] args) {
     2         
     3         
     4         /*LinkedHashMap<String, Object> map = new LinkedHashMap<String,Object>();
     5         
     6         ArrayList<String> list2 = new ArrayList<String>();
     7         list2.add("ben");
     8         list2.add("bill");
     9         map.put("B", list2);
    10         
    11         ArrayList<String> list1 = new ArrayList<String>();
    12         list1.add("alex");
    13         list1.add("alice");
    14         list1.add("allen");
    15         map.put("A", list1);
    16         
    17         System.out.println(map);*/
    18         
    19         
    20         
    21         HashMap<Student, Object> map = new HashMap<Student,Object>();
    22         
    23         ArrayList<String> list1 = new ArrayList<String>();
    24         list1.add("alex");
    25         list1.add("alice");
    26         list1.add("allen");
    27         Student s1 = new Student("001", "大狗", 20);
    28         map.put(s1, list1);
    29         
    30         
    31         ArrayList<String> list2 = new ArrayList<String>();
    32         list2.add("ben");
    33         list2.add("bill");
    34         Student s2 = new Student("001", "大狗", 20);
    35         // 修改
    36         map.put(s2, list2);
    37         System.out.println(map);
    38         
    39     }

    HashMap

    HashMap底层数据结构哈希表;key以HashSet存储。

     1 public static void main(String[] args) {
     2         
     3         /*
     4         HashMap<String, Object> map = new HashMap<String,Object>();
     5         
     6         ArrayList<String> list1 = new ArrayList<String>();
     7         list1.add("alex");
     8         list1.add("alice");
     9         list1.add("allen");
    10         map.put("A", list1);
    11         
    12         
    13         ArrayList<String> list2 = new ArrayList<String>();
    14         list2.add("ben");
    15         list2.add("bill");
    16         map.put("B", list2);
    17         
    18         System.out.println(map);
    19         */
    20         
    21         
    22         HashMap<Student, Object> map = new HashMap<Student,Object>();
    23         
    24         ArrayList<String> list1 = new ArrayList<String>();
    25         list1.add("alex");
    26         list1.add("alice");
    27         list1.add("allen");
    28         Student s1 = new Student("001", "大狗", 20);
    29         map.put(s1, list1);
    30         
    31         
    32         ArrayList<String> list2 = new ArrayList<String>();
    33         list2.add("ben");
    34         list2.add("bill");
    35         Student s2 = new Student("001", "大狗", 20);
    36         // 修改
    37         map.put(s2, list2);
    38         System.out.println(map);
    39         
    40     }

    总结:

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

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

     

  • 相关阅读:
    23种设计模式-桥接模式
    23种设计模式-单列模式
    23种设计模式-迭代器模式
    23种设计模式-组合模式
    23种设计模式-备忘录模式
    23种设计模式-适配器模式
    23种设计模式-状态模式
    SVN的安装和应用
    线程、线程池
    条形码
  • 原文地址:https://www.cnblogs.com/xfbb/p/10817249.html
Copyright © 2011-2022 走看看