zoukankan      html  css  js  c++  java
  • 十一.Java中的集合(set,map,list)

    1.集合简述:
        Iterable         Map
          |           |
        Collection     HashMap,TreeMap
          |             
         List      Set
        |         |
      ArrayList     HashSat
      LinkedList   TreeSats
      Vector

    2.数组与集合:数组与几何是密切相关的例如list的底层运用数组来实现功能
      辅助类:java.util.Arrays
    3.集合:
      辅助类:java.util.Collections

      Collection{
        Set(无序不可重复)
        List(有序可重复)
      }

      Map{HashMap,TreeMap}

      一个简单的测试类:

      Collection c=new ArrayList();
      c.add(1);
      c.add("hello");
      c.add(new Object());
      System.out.println(c.contains(1));
      System.out.println(c.size());
      System.out.println(c.remove(1));
    
      Iterator it = c.iterator();//获取集合的迭代器,可以帮助我们迭代集合中的每个元素
      while(it.hasNext()) {
        Object next = it.next();
        System.out.println(next);
      }
      c.clear();
      System.out.println(c.size());

    4.集合的特点:
      1.可存放不同类型的对象(必须是对象)
        数组只能存放同一类型数据,但是可以存放基本类型数据
      2.集合的长度可以自动增加
        集合的底层由数组实现,调用到Arrays.copy()这个方法来延长长度
      3.集合对象中有众多方法可以直接调用进行元素(数据)操作
        数组对象中没有方法可以对数据进行操作
      4.java.util包中的辅助工具类Colletions,也能对集合中的元素进行操作
        java.util包中的辅助工具类Arrays,是用来对数组中的元素进行操作的。

    5.Iterable接口
      Collection继承了这个接口
      实现这个接口的对象,可以使用"foreach"语句对其进行循环遍历.
      并且该接口中提供了一个方法可以返回一个迭代器对象,迭代器对象在这里的作用就是循环遍历集合中的每一个元素。
      public Iterator iterator();

      ArrayList这个类中有一个Itr的内部类,这个类继承了Iterator接口,所以可以说在ArrayList中,实现Iterable接口就是为了
      重写iterator方法,而这个iterator方法经过重写会返回一个Iterator类型的变量,实际上是返回的一个Itr类型的对象引用
      public Iterator<E> iterator() {
        return new Itr();
      }

      private class Itr implements Iterator<E> {.............}

      在这个Iterator类型的对象中有着几个有用的方法:

        boolean hasNext()  如果仍有元素可以迭代,则返回 true。

        E next()        返回迭代的下一个元素。

                  void remove()    从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。

      也就是说,实现iterable接口就是为了重写iterator方法,而这个Iterator接口则是由ArrayList中的内部类实现,可以说这个内部类实现了iterable中的方法。

    6.Collection接口
      Collection接口继承了Iterable接口。
      Collection类型集合体系结构中的根接口,JDK中不提供此接口的任何直接实现,而是提供更具体的子接口(List和Set)。
      Collection接口中提供了很多集合中通用的方法。
      例如:
      add 方法
      remove 方法
      clear 方法
      size 方法
      ......

      注:JDK5以上的自动装箱拆箱(就是说可以在集合中存入基本数据类型,在存入的时候会自动转换为包装类类型)
      1.在集合中添加元素
      boolean add(E e)

      2.在集合中添加集合
      boolean addAll(Collection<? extends E> c)

      3.清空集合
      void clear()

      4.判断集合中是否存在元素
      boolean contains(Object o)

      5.判断集合中是否存在集合 
      boolean containsAll(Collection<?> c)

      6.比较集合是否相等
      boolean equals(Object o)

      7.返回此 collection 的哈希码值。 
      int hashCode()

      8.判断集合是否为空
      boolean isEmpty()

      9.返回一个迭代器
      Iterator<E>iterator()

      10.根据元素值删除元素
      boolean remove(Object o)

      11.删除包含在此集合内的另一个集合
      boolean removeAll(Collection<?> c)

      12.11取反 
      boolean retainAll(Collection<?> c) 
      仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。 

      13.返回集合长度
      int size() 
      返回此 collection 中的元素数。

      //Object[] toArray() 
      返回包含此 collection 中所有元素的数组。 
      //<T>T[]
      toArray(T[] a) 
      返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。

    7.Collection类型集合的遍历

      1.通用方式: 使用集合中提供的迭代器
      Collection c = new ..;(List或Set类型都可以)
      //调用add方法存数据

      Iterator iterator = c.iterator();
      while(iterator.hasNext()){
        Object obj = iterator.next();
        System.out.println(obj);
      }

      2.List集合的特有方式:get方法通过下标访问元素
      (注:Set集合不能这样使用)
      List list = new ArrayList();
      //调用add方法存数据

      for(int i=0;i<list.size();i++){
        System.out.println(list.get(i));
      }

      3.foreach循环(增强for循环)

      注:JDK5.0版本及以上可用
      Collection c = new ..;(List或Set类型都可以)
      //调用add方法存数据
      //自动遍历集合c中的元素,并且每次使用变量o来接收
      for(Object o:c){
        System.out.println(o);
      }

      注:foreach循环也可以遍历数组

    8.List接口和Set接口
      List和Set都是Collection接口的子接口,但它们各自的特点不同。

      List类型集合特点:集合中的元素有序且可重复
      Set类型集合特点 :集合中的元素不可重复,有没有序要看Set接口具体的实现类是谁。

      注:有序指的是元素放到集合中的顺序和循环遍历出来的顺序一致

      List接口常见的实现类有:ArrayList、LinkedList、Vector等

        1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构

        2.对于数据的随机访问,ArrayList效率优于LinkedList,因为LinkedList要移动指针进行遍历查找

        3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据

        4.Vector是线程安全的集合,但是速度慢,方法是被synchronized修饰的

        5.查看API可知,List接口中是这些集合中共有的方法,而且每个集合类中又有一些自己独有的方法。

      List中的方法:

        1.向集合尾部添加元素
          boolean add(E e)

        2.向集合中的指定位置添加元素
          void add(int index, E element)

        3.将一个集合中的所有元素,添加到集合的尾部
          boolean addAll(Collection<? extends E> c)

        4.将一个集合中的所有元素,添加到集合的指定地方 
          boolean addAll(int index, Collection<? extends E> c)

        5.删除集合中的所有元素
          void clear()

        6.确定集合中是否存在这个元素
          boolean contains(Object o)

        7.确定一个集合是否包含另一个集合
          boolean containsAll(Collection<?> c)

        8.集合的equlas方法
          boolean equals(Object o)

        9.根据下标查元素
          E get(int index)

        10.根据元素查下标
          int indexOf(Object o) 

        返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。 
          int lastIndexOf(Object o) 
        返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。

        11.返回列表的哈希码
          int hashCode()

        12.判断集合是否为空
          boolean isEmpty()

        13.Iterator<E> iterator() 
          返回按适当顺序在列表的元素上进行迭代的迭代器。 
          iterator 中有两个方法:
            1.boolean hasNext()//常常作为循环条件 
            如果仍有元素可以迭代,则返回 true。 
            2.E next() //循环体中取元素
            返回迭代的下一个元素。 
            ListIterator<E>listIterator()
            返回此列表元素的列表迭代器(按适当顺序)。 
            ListIterator<E>listIterator(int index) 
            返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始。

        14.根据下标删除一个元素
          E remove(int index) 
          移除列表中指定位置的元素(可选操作)。 

        15.根据元素值删除
          boolean remove(Object o) 
          从此列表中移除第一次出现的指定元素(如果存在)(可选操作)。 

        16.删除包含在此集合内的另一个集合
          boolean removeAll(Collection<?> c) 
          从列表中移除指定 collection 中包含的其所有元素(可选操作)。 

        17.16的方法调用取反
          boolean retainAll(Collection<?> c) 
          仅在列表中保留指定 collection 中所包含的元素(可选操作)。

        16.根据下标替换
          E set(int index, E element) 
          用指定元素替换列表中指定位置的元素(可选操作)。 

        17.返回集合长度
          int size() 
          返回列表中的元素数。

          //List<E>subList(int fromIndex, int toIndex) 
          //返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。

        18.转置数组
          Object[] toArray() 
          返回按适当顺序包含列表中的所有元素的数组(从第一个元素到最后一个元素)。 
          //<T>T[] toArray(T[] a) 
          //返回按适当顺序(从第一个元素到最后一个元素)包含列表中所有元素的数组;返回数组的运行时类型是指定数组的运行时类型。

      ArrayList中的方法:

        boolean add(E e)

        void add(int index, E element)

        boolean addAll(Collection<? extends E> c)

        boolean addAll(int index, Collection<? extends E> c)

        void clear()

        //Object clone() 返回此 ArrayList 实例的浅表副本。

        boolean contains(Object o)

        E get(int index)

        int indexOf(Object o)

        int lastIndexOf(Object o)

        boolean isEmpty()

        E remove(int index)

        boolean remove(Object o)

        //protected void removeRange(int fromIndex, int toIndex) 
        移除列表中索引在 fromIndex(包括)和 toIndex(不包括)之间的所有元素。 

        E set(int index, E element)

        int size()

        //Object[] toArray() 
        按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组。 
        //<T>T[]
        toArray(T[] a) 
        按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组;返回数组的运行时类型是指定数组的运行时类型。 
        ArrayList独有!!!!!!!!!!!void trimToSize() 
        将此 ArrayList 实例的容量调整为列表的当前大小。

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

        HashSet集合中元素的特点:无序不可重复
        LinkedHashSet集合中元素的特点:有序不可重复

        思考:set集合中元素的不可重复是怎么实现的?
        hashCode 和 equlas

        Set接口的常用方法:
          1.添加一个元素
          boolean add(E e)

          2.添加一个集合 
          boolean addAll(Collection<? extends E> c)

          3.清空集合
          void clear()

          4.查找集合中是否存在这个元素
          boolean contains(Object o)

          5.判断集合是否包含指定集合
          boolean containsAll(Collection<?> c)

          6.比较两个集合是否相等
          boolean equals(Object o)

          7.返回 set 的哈希码值。 
          int hashCode()

          8.判断集合是否为空
          boolean isEmpty()

          9.返回一个迭代器
          Iterator<E>iterator()

          10.根据元素值删除元素
          boolean remove(Object o)

          11.删除此集合中包含的指定集合元素
          boolean removeAll(Collection<?> c)

          12.同11反
          boolean retainAll(Collection<?> c)

          13.返回集合长度 
          int size()

          //Object[] toArray()   
          返回一个包含 set 中所有元素的数组。 
          //<T>T[]
          toArray(T[] a) 
          返回一个包含此 set 中所有元素的数组;返回数组的运行时类型是指定数组的类型。

      SortedSet接口和TreeSet类

        SortedSet接口是Set接口的子接口,除了拥有Set集合的一些基本特点之外,还提供了排序的功能。

        TreeSet类就是SortedSet接口的实现类

        TreeSet类的排序功能
        注:TreeSet排序永远都是从小到大排,但是谁大谁小是我们的方法说了算的
        1.自然排序
          核心:让元素自身具备比较性,需要实现Comparable接口,重写其compareTo方法,比较出大小后即可进行排序

        java.lang.Comparable接口
        例如:

        public class Student implements Comparable{
          private long id;
          public long getId() {
            return id;
          }
          public void setId(long id) {
            this.id = id;
          }
          public int compareTo(Object o) {
            Student s = (Student)o;
            if(this.id<s.id){
              return -1;
            }else if(this.id>s.id){
              return 1;
            }
            return 0;
          }
        }

        注:
          s1.compareTo(s2);
          返回正数说明s1大
          返回负数说明s1小
          返回0说明s1和s2相等

        2.比较器排序(定制排序、客户化排序)
          核心:使用比较器进行元素之间的比较,比较出大小后即可进行排序。

          java.util.Comparator接口
          例如:
          main:

          Set set = new TreeSet(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
              Student s1 = (Student) o1;
              Student s2 = (Student) o2;
              return (int)(s1.getId()-s2.getId());
            }
          });

          注:比较器排序的优先级比自然排序的高

          思考:在TreeSet中整数默认是从小到大排序,字符是默认是按a-z的顺序,那么怎么能让它们的顺序是倒过来的?

          Set set = new TreeSet(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
              return -(o1.compareTo(o2));
            }
          });

    9.Collection类型集合与数组之间的转换

      Collection接口中定义了俩个方法,可以将当前集合转换为数组:

        1.Object[] toArray() 返回包含集合中所有元素的数组
          例如:
            Collection c = new ...;(List或者Set的实现类都可以)
            Object[] array = c.toArray();
            System.out.println(Arrays.toString(array));

        2.<T> T[] toArray(T[] a) 可指定返回数组的类型
          例如:
            Collection c = new ...;(List或者Set的实现类都可以)
            String[] str = new String[set.size()];
            //元素自动存放到数组str中了
            set.toArray(str);
            System.out.println(Arrays.toString(str));

      java.util.Arrays中定义了一个方法,可以将数组转换为List类型集合:

        public static <T> List<T> asList(T... a)
        例如:
          Integer[] a = new Integer[4];
          a[0] = 12;
          a[1] = 13;
          a[2] = 14;
          a[3] = 15;
          List list = Arrays.asList(a);
          for(Object o:list){
            System.out.println(o);
          }
          输出结果:
          12
          13
          14
          15
        例如:
          int[] a = new int[4];
          a[0] = 12;
          a[1] = 13;
          a[2] = 14;
          a[3] = 15;
          List list = Arrays.asList(a);
          for(Object o:list){
            System.out.println(o);
          }
          输出结果:
          [I@3cf5b814

        注意基本类型数组和引用类型数组在这里的区别

    10.Collection类型集合的工具类:Collections

       注意Collection和Collections的区别:一个是接口一个是类

       java.util.Collections类是一个工具类,类中提供了很多的静态方法对Collection类型的集合进行操作

        1.fill方法,使用指定元素替换指定列表中的所有元素。 
        例如:
          List list = new ArrayList();
          list.add(1);
          list.add(2);
          list.add(3);
          Collections.fill(list, 20);
          for(Object o:list){
            System.out.println(o);
          }

        2.max方法,根据元素的自然顺序,返回给定集合的最大元素
        例如:
          List list = new ArrayList();
          list.add(1);
          list.add(9);
          list.add(3);
          System.out.println(Collections.max(list));

        3.min方法,根据元素的自然顺序,返回给定集合的最小元素

        reverse方法,反转集合中的元素
        例如:
          List list = new ArrayList();
          list.add(1);
          list.add(9);
          list.add(3);
          Collections.reverse(list);
          for(Object o:list){
            System.out.println(o);
          }

        4.sort方法,根据元素的自然顺序,对指定列表按升序进行排序
        例如:
          List list = new ArrayList();
          list.add(1);
          list.add(9);
          list.add(3);
          Collections.sort(list);
          for(Object o:list){
            System.out.println(o);
          }

        5.shuffle方法,使用默认随机源对指定列表进行置换
        例如:
          List list = new ArrayList();
          list.add(1);
          list.add(9);
          list.add(3);
          Collections.shuffle(list);
          for(Object o:list){
            System.out.println(o);
          }

        6.还有一系列的方法,可以把集合转为相应的线程安全的集合对象
        synchronizedList
        synchronizedSet
        synchronizedMap

    11.Map接口
      Map类型的集合与Collection类型的集合不同,Map类型的集合存储数据的时候,要使用Key-Value的形式(键值对)且Key值不能重复,否则会覆盖原来的键值对

      Map接口中的一些方法
      put 方法
      get 方法
      clear 方法
      containsKey 方法
      containsValue 方法
      isEmpty 方法
      size 方法
      remove 方法

      1.清空Map集合
        void clear()

      2.是否有对应的键值元素存在 
        boolean containsKey(Object key)

      3.是否有对应的值元素存在
        boolean containsValue(Object value)

      4.返回此映射中包含的映射关系的 Set 视图。 
        Set<Map.Entry<K,V>> entrySet()

      5.比较两个集合是否相等
        boolean equals(Object o)

      6.输入key值,返回value值 
        V get(Object key)

      7.返回此映射的哈希码值。
        int hashCode()

      8.判断集合是否为空 
        boolean isEmpty()

      9.返回此映射中包含的键的 Set 视图。 
        Set<K>keySet()

      10.插入元素
        V put(K key, V value)

      11.向此集合中添加另一个集合
        void putAll(Map<? extends K,? extends V> m)

      12.根据键值删除元素
        V remove(Object key)

      13.返回集合中键值对的数量
        int size()

      14.返回此映射中包含的值的 Collection 视图。
        Collection<V>values()

      Map接口的常用实现类:HashMap类和Hashtable类

      1.HashMap是线程不安全的,Hashtable是线程安全的
      2.HashMap允许key值或者value值为null,但是Hashtable中的key值或者value值都不允许为null,否则报错.
      3.TreeMap..........................
      注:map中的key和value都必须是Object

    12.Map类型集合的遍历

      1.使用keySet方法,可以返回该Map集合中的所有key值的set类型集合

      例如:
        Map map = new HashMap();
        //调用put方法存值

        for(Object key:map.keySet()){
          System.out.println(key+" : "+map.get(key));
        }

      2.使用values方法,可以返回该Map集合中所有value值的Collection类型集合

      例如:
        Map map = new HashMap();
        //调用put方法存值

        for(Object value:map.values()){
          System.out.println(value);
        }

      3.使用entrySet方法,可以返回该Map集合中,包含所有Entry类型对象的Set集合

      Set<Map.Entry<K,V>> entrySet();
      注:Entry是声明Map接口中的内部接口(看API或源码可知),一个Entry类型对象就表示Map中的一组键值对(K-V)

      例如:
        Map map = new HashMap();
        //调用put方法存值

        Set entrySet = map.entrySet();
        for(Object obj:entrySet){
          Entry entry = (Entry)obj;
          System.out.println(entry.getKey());
          System.out.println(entry.getValue());
        }

      注意这里导入Entry接口的形式。

    13.SortedMap接口和TreeMap类

      public interface NavigableMap<K,V> extends SortedMap<K,V>

      public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Cloneable, java.io.Serializable

      SortedMap接口是Map的子接口,其进一步提供对于键s的排序功能。

      TreeMap类就是SortedMap接口的实现类。

      TreeMap可以对key值进行自然排序或者比较器排序,其用法和TreeSet是一致的。

      public V put(K key, V value) {
        Entry<K,V> t = root;
        if (t == null) {
        compare(key, key); // type (and possibly null) check

        root = new Entry<>(key, value, null);
        size = 1;
        modCount++;
        return null;
      }
      int cmp;
      Entry<K,V> parent;
      // split comparator and comparable paths
      Comparator<? super K> cpr = comparator;//从这里可以看出comparator的优先级较comparable高
      if (cpr != null) {
        do {
          parent = t;
          cmp = cpr.compare(key, t.key);
          if (cmp < 0)
            t = t.left;
          else if (cmp > 0)
            t = t.right;
          else
            return t.setValue(value);
        } while (t != null);
      } else {
        if (key == null)
          throw new NullPointerException();
        @SuppressWarnings("unchecked")
        Comparable<?super K> k = (Comparable<? super K>) key;
        do {
          parent = t;
          cmp = k.compareTo(t.key);
          if (cmp < 0)
            t = t.left;
          else if (cmp > 0)
            t = t.right;
          else
            return t.setValue(value);
        } while (t != null);
      }
      Entry<K,V> e = new Entry<>(key, value, parent);
      if (cmp < 0)
        parent.left = e;
      else
        parent.right = e;
        fixAfterInsertion(e);
        size++;
        modCount++;
        return null;
      }

    14.Entry

      TreeSet的底层是个TreeMap,而在TreeMap中有个内部类叫Entry;这个类利用泛型定义了键值成对的数据,我们发现Map中许多的方法实际上都与
      Entry这个内部类有联系;
      put方法就是需要Entry类中的setValue方法来实现的

      static final class Entry<K,V> implements Map.Entry<K,V> {
        K key;
        V value;
        Entry<K,V> left;
        Entry<K,V> right;
        Entry<K,V> parent;
        boolean color = BLACK;

        /**
        * Make a new cell with given key, value, and parent, and with
        * {@code null} child links, and BLACK color.
        */
        Entry(K key, V value, Entry<K,V> parent) {
          this.key = key;
          this.value = value;
          this.parent = parent;
        }

        /**
        * Returns the key.
        *
        * @return the key
        */
        public K getKey() {
          return key;
        }

        /**
        * Returns the value associated with the key.
        *
        * @return the value associated with the key
        */
        public V getValue() {
          return value;
        }

        /**
        * Replaces the value currently associated with the key with the given
        * value.
        *
        * @return the value associated with the key before this method was
        * called
        */
        public V setValue(V value) {
          V oldValue = this.value;
          this.value = value;
          return oldValue;
        }

        public boolean equals(Object o) {
          if (!(o instanceof Map.Entry))
          return false;
          Map.Entry<?,?> e = (Map.Entry<?,?>)o;

          return valEquals(key,e.getKey()) && valEquals(value,e.getValue());
        }

        public int hashCode() {
          int keyHash = (key==null ? 0 : key.hashCode());
          int valueHash = (value==null ? 0 : value.hashCode());
          return keyHash ^ valueHash;
        }

        public String toString() {
          return key + "=" + value;
        }
      }

    15.循环遍历,数组中的元素

      for(int i=0;i<array.length;i++){

      }

      for - each循环:for(Object obj: array){

      }

  • 相关阅读:
    vi编辑器更新...
    centos7 修改密码
    Linux的vi编辑器笔记
    linux 基本命令2(12月27日笔记)
    linux 进阶命令笔记(12月26日)
    linux 基础命令(12月25日笔记)
    谈谈CSS3中display属性的Flex布局(弹性布局)
    微信小程序页面跳转的三种方式总结
    微信小程序animation有趣的自定义动画
    微信小程序wx.setStorage(OBJECT)
  • 原文地址:https://www.cnblogs.com/Magic-Li/p/12802156.html
Copyright © 2011-2022 走看看