博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

JavaEE - 11集合Collection

Posted on 2020-12-07 22:07  Kingdomer  阅读(158)  评论(0)    收藏  举报

 

JavaEE - 11集合Collection

(1)Java集合框架概述

(1.1)数组的特点与缺点

  • 集合、数组都是对多个数据进行存储操作的结构,简称Java容器
    • 此时的存储,主要指的是内存层面的存储,不涉及到持久化的存储(.txt, .jpg,.avi,数据库)
  • 数组在存储多个数据方面的特点
    • 一旦初始化以后,其长度就确定了。
    • 数组一旦定义好,其元素的类型也确定了。只能操作指定类型的数据。如:String[] arr; int[] arr1; Object[] arr2;
  • 数组在存储多个数据方面的缺点
    • 一旦初始化以后,其长度就不可修改。
    • 数组中提供的方法非常有限,对于添加、删除、插入数据等操作,非常不便,同时效率不高。
    • 获取数组中实际元素的个数的需求,数组没有现成的属性或方法可用。
    • 数组存储数据的特点: 有序、可重复。对于无序、不可重复的需求,不能满足。
  • Java集合类可以存储数量不等的多个对象,也可用于保存具有映射关系的关联数组。

(1.2)集合使用场景

  • 客户端: 将JSON对象或JSON数组转换为Java对象或Java对象构成的List
  • 服务器端:将Java对象或Java对象构成的List 转换为JSON对象或JSON数组

(1.3)Java集合

Java集合可分为 Collection 和 Map 两种体系。
  • Collection接口:单列数据,定义了存取一组对象的方法的集合
    • List:元素有序、可重复的集合    ArrayList、LinkedList、Vector
    • Set: 元素无序、不可重复的集合  HashSet、LinkedHashSet、 TreeSet
      • SortedSet:无序、不可重复的,但是存储元素可以按照元素大小自动排序。
  • Map接口:双列数据,保存具有映射关系"key-value对"的集合。HashMap、LinkedHashMap、TreeMap(SortedMap)、Hashtable、Properties
  • 迭代器(Iterator、ListIterator)、对象排序接口(Comparable、Comparator)、容器工具类(Collections)

 

(2)Collection接口方法

  • add(Object obj):        将元素obj添加到集合中
  • int size():             获取添加的元素个数
  • addAll(Collection col): 将col集合中的元素添加到当前的集合中
  • clear():                清空集合元素
  • isEmpty():              判断当前集合是否为空
  • contains(Object obj):   判断当前集合中是否包含obj元素
  • containsAll(Collection col): 判断形参col中的所有元素是否都在当前集合中
  • boolean remove(Object obj):  通过元素的equals方法判断是否是要删除的那个元素。只会删除找到的第一个元素。
  • boolean removeAll(Collection col):  取当前集合的差集,从当前集合中移除形参col中的所有元素
  • boolean retainAll(Collection c):    把交集的结果存在当前集合中,不影响集合c
  • boolean equals(Object obj):         集合是否相等
  • Object[] toArry():                  转换成对象数组
  • hashCode():                         获取集合对象的哈希值
  • iterator():                         返回迭代器对象,用于集合遍历

(2.1)add()、size()、addAll()、clear()、isEmpty()方法

    @Test
    public void test1(){
        Collection collection = new ArrayList();
        collection.add("AA");
        collection.add("BB");
        collection.add(123);  // 自动装箱
        collection.add(new Date());
        System.out.println(collection.size()); //4

        Collection collection1 = new ArrayList();
        collection1.add("DDD");
        collection1.add(88);
        collection.addAll(collection1);
        System.out.println(collection.size()); //6

        collection1.clear();
        System.out.println(collection1.isEmpty()); //true
    }

(2.2) contains()方法

    @Test
    public void test2(){
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(new String("Tom"));
        coll.add(false);
        coll.add(new Person("aaa",12));
        System.out.println(coll);  //[123, Tom, false, Person@621be5d1]

        boolean contains = coll.contains(123);
        System.out.println(contains);   //true
        System.out.println(coll.contains(new String("Tom"))); //true
        Person p = new Person("bbb",34);
        coll.add(p);
        System.out.println(coll.contains(p)); //true
        System.out.println(coll.contains(new Person("bbb",34))); //false
    }

重写类的equals 和 hashCode方法 

    // 重写Person类的 equals 和 hashCode方法
    @Override
    public boolean equals(Object o){
        if(this == o) return true;
        if(o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        if(age != person.age) return false;
        return name != null ? name.equals(person.name) : person.name == null;
    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }

System.out.println(coll.contains(new Person("bbb",34))); //true

重新 观察contains,对象比较过程

    @Override
    public boolean equals(Object o){
        System.out.println("Person equals()......");
        ......
    }
    @Test
    public void test2(){
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(new String("Tom"));
        coll.add(false);
        coll.add(new Person("aaa",12));
        System.out.println(coll);  //[123, Tom, false, Person@621be5d1]
        // 在判断时调用obj对象所在类的equals()方法
        System.out.println(coll.contains(new Person("aaa",12))); //true  从前往后,逐一比较,找到返回true,停止比较;找不到返回false。
    }
[123, Tom, false, Person@2d8feb]
Person equals()......
Person equals()......
Person equals()......
Person equals()......
true

向Collection接口的实现类的对象中添加数据obj时,要求obj所在类要重写equals()方法。

(2.3)containsAll()方法

    @Test
    public void test3(){
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(new String("Tom"));
        coll.add(false);
        coll.add(new Person("aaa",12));


        Collection coll01 = Arrays.asList(123,false,new Person("bbb",20));
        System.out.println(coll.containsAll(coll01));  //false
}
//----------------------
Person equals()......  // new Person("bbb",20)  调用equals,一个个比较
Person equals()......
Person equals()......
Person equals()......
false

(2.4)remove()方法

    @Test
    public void test3(){
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(new String("Tom"));
        coll.add(false);
        coll.add(new Person("aaa",12));

        coll.remove(123);
        coll.remove(new Person("aaa",12));
        coll.remove("Tom");
        System.out.println(coll);  // [false]
}
//---------------------
Person equals()......
Person equals()......
Person equals()......
[false]

(2.5)removeAll()方法

    @Test
    public void test3(){
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(new String("Tom"));
        coll.add(false);
        coll.add(new Person("aaa",12));

        Collection coll02 = new ArrayList();
        coll02.add(123);
        coll02.add(456);
        coll02.add(new Person("aaa",12));
        Person p = new Person("bbb",34);
        coll02.add(p);
        System.out.println(coll02);
        coll.removeAll(coll02);
        System.out.println(coll);  // [Tom, false]
        System.out.println(coll02); // [123, 456, Person@2d8feb, Person@2e0840]
    }

(2.6)retainAll()、equals()、hashCode()方法

    @Test
    public void test4(){
        Collection coll02 = new ArrayList();
        coll02.add(123);
        coll02.add(456);
        coll02.add(new Person("aaa",12));
        coll02.add(new Person("bbb",34));

        Collection coll03 = new ArrayList();
        coll03.add(123);
        coll03.add(456);
        coll03.add(new Person("bbb",23)); 
        System.out.println(coll02.retainAll(coll03));  // 输出6个Person equals() true;  coll02的两个Person对象和coll03的每个比较,2*coll03.length
        System.out.println(coll02);   //[123, 456]

        System.out.println(coll02.equals(coll03));  //false
        System.out.println(coll02.hashCode());  //5230
    }

(2.7)集合和数组转换: toArray() / Arrays.asList()

    @Test
    public void test5(){
        Collection coll02 = new ArrayList();
        coll02.add(123);
        coll02.add(456);
        coll02.add(new Person("bbb",20));
        //集合 -> 数组: toArray()
        Object[] arr = coll02.toArray();
        for(int i = 0; i< arr.length; i++){
            System.out.println(arr[i]); // 123  456 Person@2e0832
        }
        // 数组 --> 集合
        List<String> list = Arrays.asList(new String[]{"AA","BB","CC"});
        System.out.println(list);   // [AA, BB, CC]
        List<String> list1 = Arrays.asList("aa","cc","dd");
        System.out.println(list1);  // [aa, cc, dd]
        
        List arr1 = Arrays.asList(123,456);
        System.out.println(arr1);                         // [123, 456] , size=2
        List arr2 = Arrays.asList(new int[]{123,456});
        System.out.println(arr2);                         // [[I@621be5d1], size=1
        List arr3 = Arrays.asList(new Integer[]{123,456});
        System.out.println(arr3);                         // [123, 456], size=2
    }

 

(3)Iterator迭代器接口

(3.1)iterator(): 返回Iterator接口的实例,用于遍历集合元素。

    @Test
    public void test5(){
        Collection coll02 = new ArrayList();
        coll02.add(123);
        coll02.add(456);
        coll02.add(new Person("bbb",20));

        Iterator it = coll02.iterator();
//        System.out.println(it.next());
//        System.out.println(it.next());
//        System.out.println(it.next());            // 当超出时,报异常:java.util.NoSuchElementException 
        while(it.hasNext()){                        // 迭代器推荐使用方法
            System.out.println(it.next());          // 123  456 Person@2e0832
        }
    }

(3.2)迭代器执行原理

  • hasNext():判断是否还有下一个元素。
  • next(): 指针下移; 将下移以后集合位置上的元素返回。
  • Iterator it = coll02.iterator();   指针初始位置在 集合第一个元素的上面

(3.3)使用Iterator接口遍历集合元素

  • Iterator对象称为迭代器(设计模式的一种),主要用于遍历Collection集合中的元素。
  • GOF给迭代器模式的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。
  • Collection接口继承了java.lang.Iterable接口,该接口有一个iterator()方法,
    • 那么所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象。
  • Iterator仅用于遍历集合,Iterator本身并不提供承装对象的能力。如果需要创建Iterator对象,则必须有一个被迭代的集合。
  • 集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前。

(3.4)错误使用Iterator方式

    @Test
    public void test6(){
        Collection coll02 = new ArrayList();
        coll02.add(123);
        coll02.add(456);
        coll02.add(new Person("bbb",20));

        Iterator iterator = coll02.iterator();
        while((iterator.next()) != null){
            System.out.println(iterator.next());  // 456  报错java.util.NoSuchElementException
        }

        //集合对象每次调用iterator()都会得到一个新的迭代器对象,默认游标在集合第一个元素之前
        while(coll02.iterator().hasNext()){
            System.out.println(coll02.iterator().next());  // 123 死循环
        }
    }

(3.5)remove()方法

  • Iterator可以删除集合的元素,但是在遍历过程中通过迭代器对象的remove方法,不是集合对象的remove方法。
  • 如果还未调用next()或者在上一次调用next方法之后已经调用了remove方法,再调用remove都会报illegalStateException。
    @Test
    public void test6(){
        Collection coll02 = new ArrayList();
        coll02.add(123);
        coll02.add(456);
        coll02.add(new Person("bbb",20));
        coll02.add("Tom");

        Iterator iterator = coll02.iterator();
        while (iterator.hasNext()){
            Object obj = iterator.next();
            if("Tom".equals(obj)){
                iterator.remove();
            }
        }
        System.out.println(coll02);  // [123, 456, Person@2e0832]
    }

(3.6)使用foreach遍历集合元素

  • Java5.0 提供了foreach 循环迭代访问Collection和数组。
  • 遍历操作不需获取Collection或数组的长度,无需使用索引访问元素。
  • 遍历集合的底层调用 Iterator完成操作。
  • foreach 还可以用来遍历数组。
        for(Object obj : coll02){     // for(集合元素的类型 局部变量 : 集合对象), 内部调用迭代器
            System.out.println(obj);
        }

 

    @Test
    public void test7(){
        int[] arr = new int[]{1,2,3,4,5,67,8};
        for(int i : arr){
            System.out.println(i);
        }

        String[] arrs = new String[]{"AA","CC","DDD"};
        for(int i = 0; i<arrs.length;i++){
            System.out.println(arrs[i]);
        }
        // 增强for循环
        for(String s : arrs){
            System.out.println(s);
        }
    }

 

(3.7)Enumeration、ListIterator 

  • Enumeration接口作用与iterator接口相似,但只提供了遍历vector和HashTable类型集合元素的功能,不支持元素的移除操作。
  • Enumeration速度是iterator的2倍,同时占用更少的内存。
    • 但是,iterator远比enumeration安全,因为其他线程不能够修改正在被iterator遍历的集合里面的对象。同时,iterator允许调用者删除底层集合里面的元素。
  • Iterator是ListIterator的父类接口
  • Iterator是单列集合(Collection)公共取出容器中元素的方式,ListIterator是List集合的特有取出元素方式
  • Iterator中具备的功能只有hashNext(),next(),remove();ListIterator中具备着对被遍历的元素进行增删查改的方法,可以对元素进行逆向遍历。