• java集合之Collection接口


    一、集合框架的概述

    1.集合、数组都是对多个数据进行存储操作的结构,简称java容器。此时的存储,主要是指内存层面的存储,不涉及到持久化存储(如.txt,.jpg)

    2.数组在存储多个数据方面的缺点:

    • 一旦初始化,其长度就不可改变。
    • 数组中提供的方法非常有限,对于增加、删除、插入数据等操作,非常不便,同时效率不高。
    • 获取数组中实际元素的个数的需求,数组没有现成的属性或方法可用。
    • 数组存储数据的特点:有序、可重复。对于无序、不可重复的需求不能满足。

     3.集合的概念图:

    二、集合框架

    1.Collection接口:单列集合,用来存储一个一个对象。

      1.1list接口:存储有序、可重复的数据(动态数组)

        具体实现类:ArrayList、LinkedList、Vector(并列关系)

    常用方法:

    ①contains(Object obj):判断当前集合中是否包含obj,判断的原理其实是调用obj对象所在类的equals(),所有如果obj的是String,因为String重写了equals,所有new相同的内容返回的比较结果是true。但是如果是比较一个自定义类,那么调用的便是Object中的equals,比较的就是地址,返回结果就是false。

    ②containsAll(Collection coll):判断形参coll中的所有元素是否都存在当前集合中。

    ③remove(Object obj):移除前需要比较是否相等,所有也要重写equals

    ④removeAll(Collection coll):从当前集合中移除coll中所有的元素。差集

    ⑤retainAll(Collection coll):获取当前集合和coll集合的交集,返回当前集合

    ⑥equals(Object obj):要向返回true,需要当前集合和形参集合的元素都相同。

    ⑦hashcode():返回当前对象的哈希值

    ⑧集合——>数组:toArray()

    ⑨数组——>集合:调用Arrays类的静态方法asList()

    Arrays.asList(new int【】{123,456});//这个时候,会转换为一个集合元素

    Arrays.asList(new Integer【】{123,456});//这个时候,才会转换为二个集合

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

    使用方式一:

    一个个输出,但是不清除有多少个元素,容易报异常:

    System.out.println(iterator.next());。。。。

    如果超出集合中元素的个数,就会报异常:NoSuchElementException

    使用方式二:

    用for循环来打印,这样不会手抖多打印,而且简单方便

    使用方式三:推荐方式:

    while(iterator.hasNext()){
    System.out.println(iterator.next());
    }

    错误使用方式一:

    while(coll.iterator().hasNext()){
    System.out.println(coll.iterator.next());//结果会第一个元素无限循环,因为每调用一次iterator都会生成一个新的集合
    }

    错误使用方式二:

    while((iterator.next())!=null){
    System.out.println(iterator.next());//返回不全且报异常,因为判断上调用了next指针下移,输出再次下移,等于输出一个数,指针移动两次
    }

    删除操作remove():

    可以在遍历时,删除集合中的元素,此方法不同于集合中的remove()。

    Iterator iter = coll.iterator();//回到起点
    while(iter.hasNext()){
    Object obj = iter.next();
    if(obj.equals(“Tom”)){
    iter.remove();
    }
    }

    注意:如果还未调用next()或在上一次调用next方法之后已经调用了remove方法,再调用remove会报illegalStateException。

    JDK5,0新增了foreach循环,用于遍历集合、数组,使用方法:

    for(Object obj : coll){//集合元素的类型 局部变量 : 集合对象
    System.out.println(obj);//内部其实还是iterator迭代器,也就是把coll里面的元素放入obj中
    }

    ---ArrayList:作为List接口的主要实现类;线程不安全的,效率高;底层使用Object【】 elementData存储。

    ArrayList源码分析:

    ①在JDK7.0的时候:

    ArrayList list = new ArrayList();//底层创建了一个长度为10的Object【】数组elementData。
    list.add(123);//elementData【0】 = new Integer(123);
    。。。
    list.add(11);//如果这次的添加导致底层elementData数组容量不够,则扩容。默认情况下,扩容为原来的1.5倍,同时需要将原有数组中的数据复制到新的数组中。

    结论:建议开发中使用带参的构造器:ArrayList list = new ArrayList(int capacity)

    ②在JDK8.0中的变化:

    ArrayList list = new ArrayList();//底层Object【】 elementData初始化为{},并没有创建长度。
    list.add(123);//第一次调用add()时,底层才去通过grow()创建了长度为10的数组,并将数据123添加到elementData中。
    ...
    //后续的添加和扩容操作和7.0没有区别

    结论:JDK7.0中的ArrayList的对象的创建类似于单例的饿汉式,而8.0中的创建类似于单例中的懒汉式,延迟了数组的创建,节省内存。

     常用方法:

    增:void add(Object obj)

    删:remove(int index)/remove(Object obj)

    改:set(int index,Object ele)

    查:get(int index)

    插:add(int index,Object ele)

    长度:size()

    遍历:1.Iterator迭代器方式

       2.增强for循环

       3.普通循环

    ---LinkedList:对于频繁的插入、删除操作,使用此类效率比ArrayList高;底层使用双向链表存储。

    源码分析:

    LinkedList list = new LinkedList();//内部声明了Node类型的first和last属性,默认值为null
    list.add(123);//将123封装到Node中,创建了Node对象。

    其中,Node定义为(体现了LinkedList双向链表的说法):

    private static class Node<E>{
    E item;
    Node<E> next;
    Node<E> prev;
    
    Node(Node<E> prve,E element,Node<E> next){
    this.item = element;
    this.next = next;
    this.prev = prev;
    }
    }

    ---Vector:作为List接口的古老实现类;线程安全的,效率低;底层使用Object【】 elementData。

     源码分析:

    JDK7.0和JDK8.0中通过Vector()构造器创建对象时,底层都创建了长度为10的数组,在扩容方面,默认扩容为原来数组长度的2倍。

      1.2set接口:存储无序、不可重复的数据

        具体实现类:HashSet、LinkedHashSet、TreeSet

    注意:Set所用的方法都是Collection里面定义的。

       向Set中添加的数据,其所在的类一定要重写hashCode()和equals()

       重写的hashCode()和equals()尽可能保持一致性:相等的对象必须具有相等的散列码

       重写两个方法的小技巧:对象中用作equals()比较的Field,都应该用来计算hashCode值。

    ---HashSet:作为Set接口的主要实现类;线程不安全的;可以存储null值

    1.无序性:不等于随机性。存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数据的哈希值。

    2.不可重复性:保证添加的元素按照其equals()判断时,不能返回true。即:相同的元素只能添加一个。

    3.添加元素的过程:

    我们向HashSet中添加元素a,首先调用元素a所在类的hashCode(),计算元素a的哈希值,此哈希值接着通过某种算法计算出在HashSet底层数组中的存放位置。(即:索引位置),判断数组此位置上是否已经有元素:

      如果此位置上没有其他元素,则元素a添加成功。——>情况1

      如果此位置上有其他元素b(或以链表形式存在多个元素),,则比较元素a和元素b的hash值:

        如果hash值不相同,则元素a添加成功。——>情况2

        如果hash值相同,进而需要调用元素a所在类的equals():

          equals()返回true,则元素a添加失败。

          equals()返回false,则元素a添加成功。——>情况3

    对于添加成功的情况2和情况3而言:元素a与已经存在指定索引位置上数据以链表的方式存储。

    JDK7.0:元素a放到数组中,指向原来的元素。

    JDK8.0:原来的元素在数组中,指向元素a。(七上八下)HashSet底层:数组+链表结构。

    ---LinkedHashSet:作为HashSet的子类;遍历其内部数据时,可以按照添加的顺序遍历

    原理其实同HashSet一样,额外的每个数据还维护了两个引用,记录此数据前一个数据和后一个数据。,优点就是对于频繁的遍历操作,LInkedHashSet效率高于HashSet。原理图解如下:

    ---TreeSet:可以按照添加对象的指定属性,进行排序。

    1.向TreeSet中添加的数据,要求是相同类的对象。

    2.两种排序方式:自然排序(实现Comparable接口)和定制排序(Comparator)

    3.自然排序中,比较两个对象是否相同的标准为:comparaTo()返回0,不再是equals()

    4.定制排序中,比较两个对象是否相同的标准为:compara()返回0,不再是equals()

     自然排序代码例子:

    TreeSet sa = new TreeSet();
            sa.add(new TisiGui("刘某人",20));
            sa.add(new TisiGui("张某人",34));
            sa.add(new TisiGui("欧某人",30));
            sa.add(new TisiGui("四某人",2));
            sa.add(new TisiGui("色某人",60));
    
            Iterator iterator = sa.iterator();
            while (iterator.hasNext()){
                System.out.println(iterator.next());
            }
    
    //TisiGui类中
    @Override
        public int compareTo(Object o) {
            if (o instanceof TisiGui){
                TisiGui e = (TisiGui)o;
                return this.name.compareTo(e.name);
            }else{
                throw new RuntimeException();
            }
        }
  • 相关阅读:
    python_django_sae入口配置
    Python_问题收录总结
    python_不用循环打印1-1000
    python_程序模拟浏览器请求及会话保持
    python_socket
    【SIGGRAPH】【最终幻想XV】的战斗场景实时演示的要点解说
    【SIGGRAPH】最终幻想15的渲染技术
    【SIGGRAPH】用【有说服力的照片真实】技术实现最终幻想15的视觉特效
    罪恶装备 Xrd REVELATOR 3D进化出的非照片真实视觉
    《最终幻想XV》中角色AI的意识决策系统解析
  • 原文地址:https://www.cnblogs.com/liuhuan425/p/10878168.html
Copyright © 2020-2023  润新知