Java-04 集合框架2-Collection

目录

1. Collection接口

1.1 List子接口 

1.2 泛型 

1.3 Set子接口


1. Collection接口

        Collection接口是Collection体系的根接口,定义了单值元素的容器,其下有List、Set、Queue三个重要的接口

                · List:列表接口,存储有序、允许重复的、有下标的元素;

                · Set:集合接口,存储无序、不允许重复、无下标的元素;

                · Queue:队列接口,存储有序的、无下标的、允许重复的元素。

         1)Collection接口实现的接口:

                Collection实现了Iterable接口,可通过迭代器Iterator、foreach循环遍历。

          2)Collection接口中的方法(常用):

                · boolean add(Object obj)         // 添加一个对象

                · boolean addAll(Collection C)          // 将一个集合C中的元素全部添加到另一个集合

                · void clear()               //  清空此集合中的所有元素

                · boolean contains(Object o)        // 检查此集合中是否包含o对象

                · boolean equals(Object o)           // 判断此集合是否与当前对象相等

                · boolean isEmpty()           // 判断此集合是否为空

                · boolean remove(Object o)      // 在此集合中移除o对象

                · int size()          // 返回集合中元素的个数

                · Object[] toArray()          // 将此集合转换为数组

注意:同一个实现Collection接口的容器智能存储相同类型的元素,对于不同类型的元素,可以通过将泛型修改为Object的方式进行存储。

                3)遍历元素:

                        可以采用iterator迭代器遍历容器中的元素,或者采用增强for循环:

public class Test {
    public static void main(String[] args){
        Collection<Object> collection = new ArrayList<>();
        // 添加元素
        collection.add("芒果");
        collection.add("榴莲");
        collection.add("西瓜");

        // 遍历元素
        // 1. 迭代器遍历
        // 调用iterator()方法获取迭代器
        Iterator<Object> iterator = collection.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }

        // 2. forEach循环遍历
        for (Object o:collection) {
            System.out.println(o.toString());
        }
    }
}

            

1.1 List子接口 

        1)List接口的特点:线性表接口有序(元素的添加顺序与获取/遍历顺序一致),有下标(可以通过下标访问),允许元素重复

        2)List接口实现的接口:

                List接口实现了 Collection 接口与 Iterabel 接口。

        3)List接口中的新方法: 

                · void add(int index, Object o)          // 在index位置插入对象o

                · boolean addAll(int index, Collection c)      // 将一个集合中的元素添加到此集合中index的位置,其余元素依次后移

                · Object get(int index)       // 放回集合中指定位置的元素

                · List subList(int fromIndex, int toIndex)       // 返回fromIndex与toIndex之间的集合元素

                · ListIterator listIterator()      // 返回一个ListIterator迭代器(功能更强大)

        4)ListIterator迭代器:

                与Iterator迭代器相比,ListIterator迭代器可以向前、向后添加、修改、删除元素。

public class Test {
    public static void main(String[] args){
        List<Object> list = new ArrayList<>();
        // 添加元素
        list.add("芒果");
        list.add("榴莲");
        list.add("西瓜");

        // 迭代器遍历
        // 调用listIterator()方法获取列表迭代器
        ListIterator<Object> listIterator = list.listIterator();
        // 从前向后遍历
        while ( listIterator.hasNext()){
            System.out.println( listIterator.nextIndex()+":"+listIterator.next());
        }
        // 从后向前遍历
        while (listIterator.hasPrevious()){
            System.out.println( listIterator.previousIndex()+":"+listIterator.previous());
        }
    }
}

        5)List接口的实现类

                · ArrayList:底层采用数组(动态扩容)结构实现(默认大小10),因为有索引,查询修改快,增加删除慢。  

                        源码分析:

                                默认容量  private static final int DEFAULT_CAPACITY = 10;

                                存放元素的数组  transient Object[] elementData;

                                数组元素个数:private int size;

注意:

        1)初始化:

                虽然ArrayList默认初始化容量为10的数组,但实际上ArrayList通过{}(空数组)进行的初始化,直到添加第一个元素时才会扩容为10。

        2)size 与 length:

                size返回的是底层数组中实际上有多少个元素,length返回的是数组的容量。

        3)扩容:

                ArrayList是通过grow()函数进行扩容,扩容的本质是将数组拷贝到另一个更大容量的数组(最小扩容为+1,最优扩容为扩容为原数组的1.5倍))。

                · LinkedList:底层采用双向链表实现,没有索引,增加删除快,查询慢。

                        源码分析:

                                transient int size = 0;          // 链表中的元素个数

                                transient Node<E> first;                // 头指针

                                transient Node<E> last;                 // 尾指针

注意:

        1)LinkedList底层虽然没有索引,但提供了通过index访问链表节点的方式,通过indexof(Object obj)访问元素的索引,通过get(int index)获取对应索引的元素。

        2)LinkedList中提供了iterator、listIterator两种迭代器,其中listIterator允许逆序遍历。

        3)LinkedList底层采用链表实现,无序开辟连续的存储空间,查询快,增删慢;ArrayList底层采用动态扩容的数组实现,需要开辟连续的存储空间,查询慢,增删快。

                · Vector:底层采用数组结构实现因为有索引,查询修改快,增加删除慢。

注意:  

        1)Vector有子类Stack,因此栈的底层也是采用数组实现的。

        2)与ArrayList相比,Vector虽然也是采用数组,但其运行效率低,是线程安全的。

1.2 泛型 

        1)概述:

                泛型是JDK1.5引入的一个新特性,其本质是参数化类型,将类型作为参数传递

        2)语法:

                <T ,...>         // T称为类型占位符,表示一种引用类型(任意引用类型均可以匹配)。

                T:type类型

                E:element元素

                k:key键

                V:value值

注意:只有引用类型可以作为泛型的参数出现,基本数据类型需要转换为其对应的包装类型。

         3)泛型使用

                · 泛型类:在类名之后声明泛型(类名<T>)

public class Test {
    public static void main(String[] args) {
        // 使用泛型类MyGeneric创建对象
        MyGeneric<String> myGeneric = new MyGeneric<String>();
        // 调用set方法
        myGeneric.setT("Hello");
        // 调用get方法
        System.out.println(myGeneric.getT());
    }
    static class MyGeneric<T>{
        // 使用泛型
        // 1.创建变量
        private T t;

        // 2.泛型作为方法参数
        public void setT(T t){
            this.t = t;
        }

        // 3.作为方法的返回值
        public T getT(){
            return t;
        }
    }
}

注意:在创建泛型类对象的时候要确定泛型对应的类型 

                · 泛型接口:在接口后声明泛型(接口名<T>)

public class Test {
    public static void main(String[] args) {
        // 使用泛型类MyGeneric创建对象
        MyGeneric<String> myGeneric = new MyGenericImpl();
        // 调用set方法
        myGeneric.setT("Hello");
        // 调用get方法
        System.out.println(myGeneric.getT());
    }
    
    // 泛型接口
    interface MyGeneric<T>{
        // 使用泛型
        // 1.做为方法返回值
        T getT();

        // 2.做方法参数
        void setT(T t);
    }
    
    // 实现类
    // 在实现泛型接口的时候就必须确定泛型对应的类型
    static class MyGenericImpl implements MyGeneric<String>{
        
        private String s; 

        @Override
        public String getT() {
            return s;
        }

        @Override
        public void setT(String s) {
            this.s = s;
        }
    }
}

注意:在实现泛型接口的时候需要确定泛型实际使用的参数。

                · 泛型方法:在返回值类型前声明泛型(<T> 返回值类型)

public class Test {
    // 泛型方法
    // T 表示传入参数的类型不确定
    public <T> void show(T t){
        System.out.println("泛型方法"+t);
    }
}

        4)泛型的好处

                · 提高代码的重用性;

                · 防止类型转换异常,提高代码的安全性;

1.3 Set子接口

        1)Set接口的特点:集合接口无序(元素的添加顺序与获取/遍历顺序不一致),无下标(不可以通过下标访问),不允许元素重复(最多包含一个null)。

        2)Set接口实现的接口:

                Set接口实现了 Collection 接口与 Iterabel 接口。

        3)Set接口中的新方法: 

                Set接口中的方法全部继承自Collection方法,其本身并没有定义新方法。

        4)Set的实现类:

                · HashSet:基于哈希表(数组+链表+红黑树)实现的Set集合;通过Hashcode保证了集合中的元素不重复,当存入元素的hashCode相同时,会调用equals进行确认,如果结果为true,则拒绝后者进入。

                Hashset底层是通过HashMap实现的,其无参构造方法默认调用HashMap的无参构造方法,初始化一个容量为16,扩容因子为0.75的散列表。


    /**
     * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
     * default initial capacity (16) and load factor (0.75).
     */
    public HashSet() {
        map = new HashMap<>();
    }

HashSet的存储过程

        1. 根据hascode计算保存的位置,如果位置为空则直接保存,不为空执行下一步;

        2. 执行equals方法,如果equals方法为true,则认为是重复,否则形成链表。 

        3. 当填入元素 > 散列表长度*扩容因子时,触发扩容机制,通过位移运算将散列表的长度翻倍。

        4. 当 链表长度>8 时,将链表转换为红黑树以提高查询效率。

                · TreeSet(红黑树):基于二叉树实现的Set集合;通过排列顺序实现了元素不重复;其实现了SortedSet接口,对集合元素自动排序其要求元素对象的类型必须实现Comparable接口,指定排序规则,通过CompareTo方法确定是否为重复元素。

                TreeSet的底层采用TreeMap实现,其存储结构为红黑树,其无参构造方法默认调用TreeMap的无参构造方法,初始化一个comparator = null的TreeMap。


    /**
     * Constructs a new, empty tree map, using the natural ordering of its keys.
     * All keys inserted into the map must implement the Comparable interface.  
     */
    public TreeMap() {
        comparator = null;
    }

                 TreeSet的使用:

注意:

        TreeSet 与 HashSet 有且仅有 iterator一个迭代器。

       

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值