zoukankan      html  css  js  c++  java
  • java集合简介

    java集合主要包括以下几点

    • Java 集合概述
    • Collection 接口
    • Iterator 接口
    • Set
    • List
    • Map
    • Collections 工具类
    • Enumeration

    1.java集合概述

      •Java 集合就像一种容器,可以把多个对象的引用(对象本身还在栈内存中,集合中放的是对象的引用)放入容器中。
      •Java 集合类可以用于存储数量不等的多个对象,还可用于保存具有映射关系的关联数组
      •Java 集合可分为 Set、List 和 Map 三种体系
        –Set:无序、不可重复的集合
        –List:有序,可重复的集合
        –Map:具有映射关系的集合
      在 Java5 之前,Java 集合会丢失容器中所有对象的数据类型,把所有对象都当成 Object 类型处理;从 Java5 增加了泛型以后,Java 集合可以记住容器中对象的数据类型
     
     

    2.Collection 接口,Iterator接口

      Collection 接口是 List、Set 和 Queue 接口的父接口(而不是Map的父接口,Map和Collection是并列的关系),该接口里定义的方法既可用于操作 Set 集合,也可用于操作 List 和 Queue 集合:
      Collection中的方法简介(了解Collection方法,那么对其子类的应用也就很简单了):
    public class TestCollection {
        public static void main(String[] args) {
                //1. 创建一个 Collection 接口的对象。接口对象,使用多态的方式. 
                    Collection collection = new ArrayList();
                
                    //2. Collection 重要方法说明: 
                    
                    /**
                     * 2.1 用于添加元素的:
                     * add():加入一个对象
                     * addAll():加入一组对象
                     */
                    Person p1 = new Person();
                    collection.add(p1);
                    collection.add(new Person());
                    
                    Collection collection2 = new ArrayList();
                    collection2.add(new Person());
                    collection2.add(new Person());
    
                    collection.addAll(collection2);
                    
                    System.out.println(collection.size()); 
                    
                    /**
                     * 2.2 用于访问集合的方法: 
                     * size():获取集合的长度: 
                     * iterator():对集合进行遍历的方法,可以得到对应的 Iterator 接口对象. 
                     * 
                     * Iterator: 迭代器
                     * ①. 获取 Iterator 接口对象: 
                     * ②. 使用 while 循环和 Iterator 对象遍历集合中的每一个元素. 具体使用 Iterator 接口的
                     *    hasNext() 和 next() 方法. 
                     */
                    Iterator iterator = collection.iterator();
                    
                    while(iterator.hasNext()){
                        Object obj = iterator.next();
                        System.out.println(obj); 
                    }
                    
                    /**
                     * 2.3 移除集合中的元素: 
                     * remove(): 移除某一个指定的对象. (API中)通过调用对象的 equals() 方法来判断要移除的那个元素在集合中是否存在. 以及是否能够成功移除. 
                     *           也就是说拿当前对象和集合中的对象一个个的比,如果有相同的equal返回true,就可以移除掉
                     *           但是如果在Person里面重写了equals()方法,而且始终返回false,那么就永远也无法移出一个Person对象
                     * removeAll():移出一组对象
                     * clear(): 使集合中的元素置空. 
                     */
                    collection.clear();
                    
                    boolean result = collection.remove(p1);
                    System.out.println(result); 
                    
                    result = collection.removeAll(collection2);
                    
                    System.out.println(collection.size()); 
                    
                    /**
                     * 2.4 用于检测集合的方法
                     * retains():是否包含一个对象
                     * retainsAll():是否包含一个对象集合
                     * isEmpty()
                     * 
                     */
                    System.out.println(collection.contains(new Person()));//false
                    System.out.println(collection.contains(p1));//true
                    System.out.println(collection.containsAll(collection2));//true
                    
                    System.out.println(collection.isEmpty()); //false
                    collection.clear();
                    System.out.println(collection.isEmpty()); //true
                    
                    /**
                     * 2.5 其他方法
                     * toArray(): 返回集合对应的数组对象
                     * T [] toArray(T[]): 涉及到泛型(比如传入参数是一个Person对象数组,那么返回值也是一个Person对象数组)
                     * 
                     * equals(): 比较两个集合是否相等.
                     *          如果是ArrayList,不仅长度和每个对象都要一样,而且顺序也要一样,因为ArrayList是有顺序的
                     *          对于HashSet就没有顺序要求 
                     * hasCode(): 返回集合的哈希码
                     */
                    Object [] objs = collection.toArray();
                    System.out.println(objs.length); //4
                    
                    Person p2 = new Person();
                    
                    Collection collection3 = new HashSet();
                    collection3.add(p1);
                    collection3.add(p2);
                    
                    Collection collection4 = new HashSet();
                    collection4.add(p2);
                    collection4.add(p1);
                    
                    System.out.println(collection3.equals(collection4)); 
                    
                    /**
                     * 使用增强 for 循环的方式来对集合进行遍历
                     */
                    for(Object obj: collection){
                        System.out.println(obj); 
                    }
            }
      }


    3.Set

          Set接口是Collection的子接口,所以前面讲的方法都可以用

          Set中包含

        HashSet
        LinkedHashSet
        TreeSet
      •Set 集合不允许包含相同的元素判定相同元素的标准是, 两个对象各调用 equals() 方法, 返回 true
      •Set 判断两个对象是否相同不是使用 == 运算符,而是根据 equals 方法
    3.1 HashSet
      HashSet 是 Set 接口的典型实现,大多数时候使用 Set 集合时都使用这个实现类。
      •HashSet 按 Hash 算法来存储集合中的元素,因此具有很好的存取和查找性能。
      •HashSet 具有以下特点:
        –不能保证元素的排列顺序
        –HashSet 不是线程安全的
        –集合元素可以使 用null
     
     
    public static void main(String[] args) {        
            Set set = new HashSet();
            //可以存放null
            set.add(null);
            System.out.println(set.size()); //1
            
            //存放同一个对象
            Person p1 = new Person();
            set.add(p1);
            set.add(p1);
            System.out.println(set.size()); //2
            
            //存放两个对象,当对象各个属性相同时,也要只存一次
            //这种情况必须重写待存入类Person类的hashCode和equals方法
            set.add(new Person("AA", 12));
            set.add(new Person("AA", 12));
            System.out.println(set.size()); //3
            
            //输出结果是不按顺序的
            set.add(new Person("FF", 13));        
            Iterator it = set.iterator();
            while(it.hasNext()){
                System.out.println(it.next()); 
            }
        }
     1 public class Person {
     2     private String name;
     3     private int age;
     4     
     5     public Person(String name, int age) {
     6         super();
     7         this.name = name;
     8         this.age = age;
     9     }
    10     public Person() {
    11         super();
    12     }
    13     @Override
    14     public int hashCode() {
    15         final int prime = 31;
    16         int result = 1;
    17         result = prime * result + age;
    18         result = prime * result + ((name == null) ? 0 : name.hashCode());
    19         return result;
    20     }
    21     @Override
    22     public boolean equals(Object obj) {
    23         if (this == obj)
    24             return true;
    25         if (obj == null)
    26             return false;
    27         if (getClass() != obj.getClass())
    28             return false;
    29         Person other = (Person) obj;
    30         if (age != other.age)
    31             return false;
    32         if (name == null) {
    33             if (other.name != null)
    34                 return false;
    35         } else if (!name.equals(other.name))
    36             return false;
    37         return true;
    38     }    
    39 }
    Person类(重写了hashCode方法和equals方法)


          Set的add方法时,调用了equals方法,查看是否有返回值为true的对象。同样,add方法同时也调用了hashCode,根据方法的返回的该对象的hashCode值来决定该对象的存储位置。

          默认情况下,如果两个对象equals的返回值是true,那么对应的hashCode值一定相等。所以存储的位置是一样的,只能存一次。

          但是如果equals返回值是true,而hashCode值不相等呢?(这种情况仅限于测试)
          我们可以看hashCode方法的源码:
     
    //根据对象的属性生成一个hashCode值
        //但是如果属性各个不相等,那么最后加起来可能就相等了
        //这里定义了prime这个素数来解决这个问题
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + age;
            result = prime * result + ((name == null) ? 0 : name.hashCode());
            return result;
        }

      我们把它改成:

        private static int init = 0;
    
    @Override
    public int hashCode() { return init++; }


      这样任何两个对象的hashCode都不会再相等了。hashSet将会把它们存储在不同的位置,依然可以添加成功(正常开发中不会出现这种情况)。

         所以:
      HashSet 集合判断两个元素相等的标准:两个对象通过 equals() 方法比较相等,并且两个对象的 hashCode() 方法返回值也相等。
      如果两个对象通过 equals() 方法返回 true,这两个对象的 hashCode 值也应该相同。
      重写 hashCode() 方法的基本原则
        –在程序运行时,同一个对象多次调用 hashCode() 方法应该返回相同的值
        –当两个对象的 equals() 方法比较返回 true 时,这两个对象的 hashCode() 方法的返回值也应相等
        –对象中用作 equals() 方法比较的 Field,都应该用来计算 hashCode 值


    3.2 LinkedHashSet

      •LinkedHashSet 是 HashSet 的子类
      •LinkedHashSet 集合根据元素的 hashCode 值来决定元素的存储位置,但它同时使用链表维护元素的次序,这使得元素看起来是以插入顺序保存的(空间位置是是无序的,但是却用链表来维护插入的顺序)。
      •LinkedHashSet 性能插入性能略低于 HashSet(插入的时候要维护顺序),但在迭代访问 Set 里的全部元素时有很好的性能。
      •LinkedHashSet 不允许集合元素重复
     
    public static void main(String[] args) {        
            Set set = new LinkedHashSet();
    
            set.add(null);
            Person p1 = new Person();
            set.add(p1);
            set.add(p1);
    
            set.add(new Person("AA", 12));
            set.add(new Person("AA", 12));
            
            set.add(new Person("FF", 13));        
            Iterator it = set.iterator();
            while(it.hasNext()){
                System.out.println(it.next()); 
            }
        }
      
    //返回结果是 返回结果的顺序就是插入的顺序
    //  null
    //  com.atguigu.java.Person@3c1
    //  com.atguigu.java.Person@d55
    //  com.atguigu.java.Person@e14


    3.3 TreeSet

       TreeSet 是 SortedSet 接口的实现类,TreeSet 可以确保集合元素处于排序状态
        –Comparator comparator()
        –Object first()
        –Object last()
        –Object lower(Object e)
        –Object higher(Object e)
        –SortedSet subSet(fromElement, toElement)  
        –SortedSet headSet(toElement)
        –SortedSet tailSet(fromElement)
      TreeSet 支持两种排序方法:自然排序和定制排序(比如按年龄,性别排序)。默认情况下,TreeSet 采用自然排序。
      
         排序:
               TreeSet 会调用集合元素的 compareTo(Object obj) 方法来比较元素之间的大小关系,然后将集合元素按升序排列。
        如果试图把一个对象添加到 TreeSet 时,则该对象的类必须实现 Comparable 接口
       实现
        实现Comparable 接口必须实现 compareTo(Object obj) 方法,两个对象即通过 compareTo(Object obj) 方法的返回值来比较大小。
     
      1.自然排序
         因为只有相同类的两个实例才会比较大小,所以向 TreeSet 中添加的应该是同一个类的对象
         当需要把一个对象放入 TreeSet 中,重写该对象对应的 equals() 方法时,应保证该方法与 compareTo(Object obj) 方法有一致的结果:如果两个对象通过 equals() 方法比较返回 true,则通过 compareTo(Object obj) 方法比较应返回 0(正数表示大于,负数表示小于)
      比如Person类实现了Comparable接口:
     
     1 public class Person implements Comparable{
     2     private String name;
     3     private int age;
     4     
     5     public Person(String name, int age) {
     6         super();
     7         this.name = name;
     8         this.age = age;
     9     }
    10     public Person() {
    11         super();
    12     }
    13     
    14     
    15     @Override
    16     public int hashCode() {
    17         final int prime = 31;
    18         int result = 1;
    19         result = prime * result + age;
    20         result = prime * result + ((name == null) ? 0 : name.hashCode());
    21         return result;
    22     }
    23     @Override
    24     public boolean equals(Object obj) {
    25         if (this == obj)
    26             return true;
    27         if (obj == null)
    28             return false;
    29         if (getClass() != obj.getClass())
    30             return false;
    31         Person other = (Person) obj;
    32         if (age != other.age)
    33             return false;
    34         if (name == null) {
    35             if (other.name != null)
    36                 return false;
    37         } else if (!name.equals(other.name))
    38             return false;
    39         return true;
    40     }
    41     @Override
    42     public int compareTo(Object o) {
    43         if(o instanceof Person){
    44             Person stu = (Person) o;
    45             return this.age - stu.age;
    46         }else{
    47             throw new ClassCastException("不是一个Student对象. ");
    48         }
    49     }
    50     @Override
    51     public String toString() {
    52         return "Person [name=" + name + ", age=" + age + "]";
    53     }    
    54 }
    实现了Comparable接口的Person类

           那么进行排序输出:

    public static void main(String[] args) {        
    
        Set set = new TreeSet();
        
        set.add(new Person("AA", 98));
        set.add(new Person("BB", 50));
        set.add(new Person("CC", 95));
        
        System.out.println(set.size());     
        for(Object obj: set){
            System.out.println(obj); 
        }
        
      }
    //f返回值是:
    // 3
    //  Person [name=BB, age=50]
    //  Person [name=CC, age=95]
    //  Person [name=AA, age=98]

      默认是升序排序,如何倒序呢?

    //倒序:返回比较结果的相反数
        @Override
        public int compareTo(Object o) {
            if(o instanceof Person){
                Person stu = (Person) o;
                return -(this.age - stu.age);
            }else{
                throw new ClassCastException("不是一个Person对象. ");
            }
        }

      如何根据name字段进行排序呢?

    //name排序:字符串已经实现了Compareable接口
        @Override
        public int compareTo(Object o) {
            if(o instanceof Person){
                Person stu = (Person) o;
                return this.name.compareTo(stu.name);
            }else{
                throw new ClassCastException("不是一个Person对象. ");
            }
        }

          如果equals方法和comparableTo方法的返回值不一样,会出现怎么样的结果?

    public static void main(String[] args) {        
    
        Set set = new TreeSet();
        
        set.add(new Person("AA", 98));
        set.add(new Person("BB", 90));
        set.add(new Person("CC", 95));
        set.add(new Person("DD", 98));
        
        System.out.println(set.size());     
        for(Object obj: set){
            System.out.println(obj); 
        }
        
      }
    //返回值是:
    // 3
    //  Person [name=BB, age=90]
    //  Person [name=CC, age=95]
    //  Person [name=AA, age=98]

           插入了四个对象,为什么才有三个成功呢?Person类里是重写了equals方法,而且实现了Comparable 接口 compareTo(Object obj) 方法,并按age字段排序。

    当在添加元素时,从Set的角度,四个对象equals方法返回的值都不一样,都应该添加,但是从TreeSet的角度,它是排序添加,添加时第一个对象和第四个对象compareTo返回的值是相等的所以又不能添加了。


      2.定制排序

      自然排序要求在创建一个加入TreeSet的类时,必须实现Comparable接口,定制排序则不需要。
      如果需要实现定制排序,则需要在创建 TreeSet 集合对象时,提供一个 Comparator 接口的实现类对象。由该 Comparator 对象负责集合元素的排序逻辑
        /**
         * 定制排序: 创建 TreeSet 对象时, 传入 Comparator 接口的实现类. 
         *    要求: Comparator 接口的 compare 方法的返回值和 两个元素的 equals() 方法具有一致的返回值  
         * @param args
         */
    public static void main(String[] args) {    
        //创建一个内部类
        Comparator comparator = new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                if(o1 instanceof Person && o2 instanceof Person){
                    Person p1 = (Person) o1;
                    Person p2 = (Person) o2;
                    return p1.getAge() - p2.getAge();                
                }else{
                    throw new ClassCastException("不能转为 Person");
                }
            }
        };
        
        Set set2 = new TreeSet<>(comparator);
        set2.add(new Person("BB", 12));
        set2.add(new Person("CC", 16));
        set2.add(new Person("DD", 15));
        
        for(Object obj: set2){
            System.out.println(obj); 
        }
        
      }
    //f返回值是:
    // 3
    //  Person [name=BB, age=12]
    //  Person [name=CC, age=15]
    //  Person [name=AA, age=16]


    4. List

    http://www.cnblogs.com/tech-bird/p/3635032.html

      •List 代表一个元素有序、且可重复的集合,集合中的每个元素都有其对应的顺序索引
      •List 允许使用重复元素,可以通过索引来访问指定位置的集合元素
      •List 默认按元素的添加顺序设置元素的索引。
      •List 集合里添加了一些根据索引来操作集合元素的方法
        –void add(int index, Object ele)
        –boolean addAll(int index, Collection eles)
        –Object get(int index)
        –int indexOf(Object obj)
        –int lastIndexOf(Object obj)
        –Object remove(int index)
        –Object set(int index, Object ele)
        –List subList(int fromIndex, int toIndex)
     
      •List 额外提供了一个 listIterator() 方法,该方法返回一个 ListIterator 对象, ListIterator 接口继承了 Iterator 接口,提供了专门操作 List 的方法:
        –boolean hasPrevious()
        –Object previous()  (可以往前遍历(因为有序),获得前一个元素)
        –void add()
     
      •ArrayList 和 Vector 是 List 接口的两个典型实现
      区别:
        –是一个古老的集合,通常建议使用 ArrayList
        –ArrVector ayList 是线程不安全的,而 Vector 是线程安全的。
        –即使为保证 List 集合线程安全,也不推荐使用 Vector


    4.1 ArrayList

       ArrayList遍历的三种方式

    public static void main(String[] args) {    
        List list = new ArrayList();
        
        list.add(new Person("AA", 12));
        list.add(new Person("BB", 13));
        list.add(new Person("CC", 14));
        list.add(new Person("DD", 15));
        
        //对 list 进行遍历
        Iterator it = list.iterator();
        while(it.hasNext()){
            System.out.println(it.next()); 
        }
        
        //使用 for 循环的方式对 list 进行遍历: 增强的 for 循环
        for(Object obj: list){
            System.out.println(obj); 
        }
        
        //使用 for 循环的方式对 list 进行遍历: 使用 List 的 get(int) 方法
        for(int i = 0; i < list.size(); i++){
            System.out.println(list.get(i)); 
        }
        
        //使用ListIterator进行遍历(hasNext()和hasPrevious向后和向前)
        ListIterator lit = list.listIterator();
        while(lit.hasNext()){
            System.out.println(lit.next());
        }
        }

      indexOf方法:获取一个元素在集合中的位置。那么首先得知道这个元素在集合中存在不存在,靠的是equals方法。

    public static void main(String[] args) {    
        List list = new ArrayList();
        
        list.add(new Person("AA", 12));
        list.add(new Person("BB", 13));
        list.add(new Person("CC", 14));
        list.add(new Person("DD", 15));
        System.out.println(list.indexOf(new Person("BB", 13)));
    }

         同前面讲的一样,必须让Person类重写equals方法,才能返回1,否则返回 -1
         其他方法:

    public static void main(String[] args) {    
        List list = new ArrayList();
        
        list.add(new Person("AA", 12));
        list.add(new Person("BB", 13));
        list.add(new Person("CC", 14));
        list.add(new Person("DD", 15));
        //把一个元素放到指定的位置
        list.add(2, new Person("EE", 16)); 
        //把一个元素加到末尾
        list.add(new Person("EE", 16));    
        //获取指定元素在集合中的第一个位置
        System.out.println(list.indexOf(new Person("EE", 16)));  //2
        //获取指定元素在集合中的最后一个位置
        System.out.println(list.lastIndexOf(new Person("EE", 16))); //5
        //相当于rePlace,把元素替换指定位置的元素
        list.set(3, new Person("AA", 12)); 
        //获取一个指定区间的集合(半闭半开区间)
        List list2 = list.subList(2, 5); //2, 3, 4
        }
     
      Arrays.asList(…) 方法
        返回的 List 集合即不是 ArrayList 实例,也不是 Vector 实例。 Arrays.asList(…)  返回值是一个固定长度的 List 集合
     
    public static void main(String[] args) {    
        
        System.out.println(Arrays.asList(new Person("MM", 23), new Person("NN", 24)));
        }
      }
    //f返回值是:
    // [Person [name=MM, age=23], Person [name=NN, age=24]]

          集合和数组之间的转化:

           1.  public static <T> List<T> asList(T... a)

              List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");

           2.   Object[] toArray() 或者 <T> T[] toArray(T[] a)

     5.Map 

      •Map 用于保存具有映射关系的数据,因此 Map 集合里保存着两组值,一组值用于保存 Map 里的 Key,另外一组用于保存 Map 里的 Value
      •Map 中的 key 和  value 都可以是任何引用类型的数据
      •Map 中的 Key 不允许重复,即同一个 Map 对象的任何两个 Key 通过 equals 方法比较中返回 false
      •Key 和 Vlaue 之间存在单向一对一关系,即通过指定的 Key 总能找到唯一的,确定的 Value。
      Map接口的子类:
        HashMap
        Hashtable
          LinkedHashMap
        TreeMap
        Properties
     
    5.1  HashMap
         从上面的关系图中,可以看出,Map和Collection接口处于同级的顶级接口。Set是通过Map来实现的
        Map接口的定义: 
    public interface Map<K,V> {
        //.....
    }

         Map接口的方法:

    public static void main(String[] args) {    
        //Map接口的典型实现是HashMap
        Map map = new HashMap();
        
        //1. 向 Map 中添加元素的: 
        //   put(key, value); 放入一个指定的键值对
        //   put(map) 放入一组键值对
        map.put("AA", new Person("AA", 12));
        map.put("AA", new Person("AAA", 12)); //key值重复,会把上一个覆盖
        map.put("CC", new Person("CCC", 12));
        map.put("MM", new Person("MMM", 12));
        map.put("II", new Person("AAA", 12));
        
        //2. 从 Map 中取出元素的(遍历)
        //2.1 得到键的集合: keySet(). 
        Set keySet = map.keySet(); //用Set,不可重复
        for(Object key: keySet){
            //利用键得到值: get(key)
            Object value = map.get(key); 
            System.out.println(key + ": " + value);
        }
        
        //2.2 直接得到 value 的集合
        Collection values = map.values();  //用Collection,可以重复
        System.out.println(values.getClass()); 
        for(Object val: values){
            System.out.println(val); 
        }
        
        //2.3 得到 键值对的 集合(泛型)
        //   首先要把前面Map对象的定义改成  Map<String,Object> map = new HashMap<>();
        for(Map.Entry<String, Object> entry: map.entrySet()){
            String key = entry.getKey();
            Object val = entry.getValue();
            
            System.out.println(key + ": " + val); 
        }
        
        //3. 移除元素的
        map.remove("AA");
        
        //4. 工具方法: 
        //4.1 size() 方法
        System.out.println(map.size()); 
        System.out.println(map); 
                
        //4.2 contains(); isEmpty()
        System.out.println(map.containsKey("BB"));
        System.out.println(map.isEmpty());             
        }


    HashMap和HashSet的关系

      HashMap 定义了 HashSet: HashMap 的键为 HashSet 里边的元素.
      我们前面说Set是通过Map来实现的,可以通过查看API文档
    public class HashSet<E>
        extends AbstractSet<E>
        implements Set<E>, Cloneable, java.io.Serializable
    {
        static final long serialVersionUID = -5024744406713321676L;
    
        private transient HashMap<E,Object> map;
    
        // Dummy value to associate with an Object in the backing Map
        private static final Object PRESENT = new Object();
    
        public Iterator<E> iterator() {
            return map.keySet().iterator();
        }
    
        public int size() {
            return map.size();
        }
        public boolean isEmpty() {
            return map.isEmpty();
        }
    
    
        public boolean contains(Object o) {
            return map.containsKey(o);
        }
        //............
    }

          可以看出,在HashSet里面维护了一个HashMap对象,其中的Key值就是HashSet里的元素(无序,不重复),Value值是一个Object类型的常量。所以对HashSet的操作都是通过调用HashMap来实现的。
          所以HashMap与HashSet相似之处

    • Key值无序,不重复
    • HashMap 可以使用 null 作为 key 和 value
    • HashMap 判断两个 Key 相等的标准是:两个 Key 通过 equals 方法返回 true,hashCode 值也相等。
    • HashMap 判断两个 Value相等的标准是:两个 Value 通过 equals 方法返回 true 

    5.2 HashTable

      •HashMap 和 Hashtable 是 Map 接口的两个典型实现类
      •区别:
        –Hashtable 是一个古老的 Map 实现类,不建议使用
        –Hashtable 是一个线程安全的 Map 实现,但 HashMap 是线程不安全的。
        - Hashtable 不允许使用 null 作为 key 和 value,而 HashMap 可以

    5.3 LinkedHashMap

          同样,LinkedHashMap也定义了LinkedHashSet
      •LinkedHashMap 是 HashMap 的子类
      •LinkedHashMap 可以维护 Map 的迭代顺序:迭代顺序(遍历顺序)与 Key-Value 对的插入顺序一致
     
    public LinkedHashSet() {
            super(16, .75f, true);
        }
    
    
    
     HashSet(int initialCapacity, float loadFactor, boolean dummy) {
            map = new LinkedHashMap<>(initialCapacity, loadFactor);
        }
    5.4 TreeMap
     
      •TreeMap 存储 Key-Value 对时,需要根据 Key 对 key-value 对进行排序。TreeMap 可以保证所有的 Key-Value 对处于有序状态。
      •TreeMap 的 Key 的排序:(与前面TreeSet排序方式一致)
        –自然排序:TreeMap 的所有的 Key 必须实现 Comparable 接口,而且所有的 Key 应该是同一个类的对象,否则将会抛出 ClasssCastException
        –定制排序:创建 TreeMap 时,传入一个 Comparator 对象,该对象负责对 TreeMap 中的所有 key 进行排序。此时不需要 Map 的 Key 实现 Comparable 接口
     
    public TreeSet() {
            this(new TreeMap<E,Object>());
        } 

          比如:

      public static void main(String[] args) {    
          Comparator comparator = new Comparator() {
                @Override
                public int compare(Object o1, Object o2) {
                    
                    Person p1 = (Person) o1;
                    Person p2 = (Person) o2;
                    
                    return p1.getAge() - p2.getAge();
                }
            };
            
            TreeMap tm = new TreeMap(comparator);
            tm.put(new Person("AA", 12), "AAA");
            tm.put(new Person("BB", 22), "AAA");
            tm.put(new Person("CC", 2), "AAA");
            tm.put(new Person("DD", 9), "AAA");
            
            Set  keySet = tm.keySet();
            for(Object key: keySet){
                Object val = tm.get(key);
                System.out.println(key + ": " + val); 
            }
      }    
    }
    //返回值是:
    // 
    //  Person [name=CC, age=2]: AAA
    //  Person [name=DD, age=9]: AAA
    //  Person [name=AA, age=12]: AAA
    //  Person [name=BB, age=22]: AAA


    5.5 Properties

      •Properties 类是 Hashtable 的子类,该对象用于处理属性文件
      •由于属性文件里的 key、value 都是字符串类型,所以 properties 里的 Key 和 Value 都是字符串类型的

          属性(Properties)文件在Java 中对一个的是一个 Properties 类的对象
          如何加载一个属性文件:

      首先要new一个File,命名为 jdbc.properties,内容为:

    url=jdbc:mysql:///test
    driver=com.mysql.jdbc.Driver
    user=root
    password=1230

          获取信息: 

      public static void main(String[] args) throws Exception {    
          /**
             * properties 文件在 Java 中对一个的是一个 Properties 类的对象
             */
            //1. 创建一个 Properties 类的对象
            Properties properties = new Properties();
            
            //2. 使用 IO 流加载对应的 properties 文件
            //   文件一定要和src同目录,否则要写全路径
            properties.load(new FileInputStream("jdbc.properties"));
            
            //3. 得到对应的属性值(通过键来获取值)
            String url = properties.getProperty("url");
            
            System.out.println(url); 
      }    


    6.Collections 工具类

           Collection是一个接口,而Collections 是一个操作 Set、List 和 Map 等集合的工具类(含有的工具方法全部都是静态方法) 

      •Collections 中提供大量方法对集合元素进行排序、查询和修改等操作,还提供对集合对象设置不可变、对集合对象实现同步控制等方法
      •排序操作:
        –reverse(List):反转 List 中元素的顺序
        –shuffle(List):对 List 集合元素进行随机排序
        –sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
        –sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
        –swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换 
    static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll)
    Returns the minimum element of the given collection, according to the natural ordering of its elements.
    static <T> T min(Collection<? extends T> coll, Comparator<? super T> comp)
    Returns the minimum element of the given collection, according to the order induced by the specified comparator.

      又比如这两个方法,都是获取集合中最小的元素,第一个方法要求 集合中的元素必须要实现Comparable接口,第二个要求集合本身实现了Comparator(利用内部类)

         对List进行排序

     public static void main(String[] args) throws Exception {    
          List list = new ArrayList();
            
            list.add(new Person("AA", 12));
            list.add(new Person("BB", 11));
            list.add(new Person("CC", 5));
            list.add(new Person("DD", 10));
            
            //使用 Collections 中的方法对 List 中的元素进行排序
            Collections.sort(list, new Comparator() {
                @Override
                public int compare(Object o1, Object o2) {
                    Person p1 = (Person) o1;
                    Person p2 = (Person) o2;
                    return - p1.getAge() + p2.getAge();
                }
            });
            
            for(Object obj: list){ 
                System.out.println(obj);
            }
      }    

            同步控制方法:       

            前面说ArrayList是线程不安全的,那么可以把它变成安全的

         List list = Collections.synchronizedList(new ArrayList<>());

             这样得到的list对象就是线程安全的。(只要传入一个集合,出来的集合就是线程安全的)

            同理,Set,Map,Collection都有类似的方法

    //获取线程安全的 List 对象, 使用 synchronizedList()
            List list2 = Collections.synchronizedList(new ArrayList<>());


      当我们操作集合的时候,如果觉得需要什么方法,都可以到Collections 类中来找

    7 .Enumeration

      Enumeration 接口是 Iterator 迭代器的 “古老版本”
     
    //对 Enumeration 对象进行遍历: hasMoreElements() nextElement()
            Enumeration names = Collections.enumeration(list);
            
            while(names.hasMoreElements()){
                Object obj = names.nextElement();
                System.out.println(obj); 
            }

      使用的时候,不会创建一个Enumeration对象,而是根据一些API得到Enumeration对象,然后进行遍历

  • 相关阅读:
    2017年5月24日 HTML 基础知识(二)
    2017年5月22日 HTML基础知识(一)
    尼采语录
    Unicode字符串和整数和浮点数
    转义字符
    python第一节
    C# ASP .NET WEB方向和WPF方向,我该如何去选择
    ORA-06550:line 1,column 7;PLS-00201:indentifer '存储过程' must be declared;...PL/SQL Statement ignored 问题
    C# WPF打印报表
    Sql Server 自定义数据类型
  • 原文地址:https://www.cnblogs.com/tech-bird/p/3528020.html
Copyright © 2011-2022 走看看