4.0 集合-数据结构-ArrayList、LinkedList类

集合的体系结构

图片[1]-4.0 集合-数据结构-ArrayList、LinkedList类-IT熊技术站

Collection概述和使用

  • 是单例集合的顶层接口,它表示一组对象,这些对象也称为Collection的元素
  • JDK不提供此接口的任何直接实现,它可以使用其子接口(List和Set)的具体类实现
  • 使用多态的方式创建其对象

Collection单列集合常用方法

图片[2]-4.0 集合-数据结构-ArrayList、LinkedList类-IT熊技术站

代码演示 :

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;

public class CollectionMethodDemo {
    /*
        Collection单列集合常用方法 :
     */
    public static void main(String[] args) {
        Collection<String> c = new ArrayList<>();

        c.add("张三");
        c.add("李四");
        c.add("王五");

        boolean b = c.remove("李四");
        System.out.println(b);

        System.out.println("--------------------");

        System.out.println(c.contains("李四"));
        System.out.println(c.contains("张三"));

        System.out.println("--------------------");

        System.out.println(c.isEmpty());
        c.clear();
        System.out.println(c.isEmpty());

        System.out.println("--------------------");

        System.out.println(c.size());
    }

    private static void method() {
        // 对象的创建: 使用多态的形式创建
        // 目的: 多态调用方法, 只能调用共有方法
        Collection<String> c = new ArrayList<>();

        c.add("张三");
        c.add("张三");
        c.add("张三");

        System.out.println("清空前: " + c);

        c.clear();

        System.out.println("清空后: " + c);
    }
}

集合的通用遍历格式

迭代器(代码演示)

/*
	集合的通用遍历方式 : 迭代器(Iterator)遍历

            1. 通过集合对象, 获取迭代器
            2. 循环判断, 集合中是否存在元素
            3. 调用方法取出元素
*/
private static void method1(Collection<Student> c) {
    // 1. 通过集合对象, 获取迭代器
    Iterator<Student> it = c.iterator();

    // Iterator<Student> it = new Itr();

    // 2. 循环判断, 集合中是否存在元素
    while (it.hasNext()) {
        // 3. 调用方法取出元素
        Student stu = it.next();   // next() : 先将元素取出来, 再将内部的指针向后移动一位
        System.out.println(stu);
    }
}

增强for(代码演示)

/*
    增强for循环 : 迭代器的语法糖
        - 底层实现也是迭代器
        - 格式 :
        for(容器中存储的元素类型 变量名 : 要遍历的容器名字){
        // 变量名 : 就是从容器中取出的元素
    }
*/
private static void method2(Collection<Student> c) {
    for (Student stu : c) {
        System.out.println(stu);
    }
}

foreach(代码演示)

/*
	调用集合的foreach方法进行遍历

    public default void forEach(Consumer<? super T> action) :

                    Consumer : 函数式接口
                    形参是接口, 实际参数该给实现类对象
                    	1. 单独编写一个实现类
                        2. 匿名内部类
                        3. Lambda
*/
public static void main(String[] args) {

    Collection<Student> c = new ArrayList<>();

    c.add(new Student("张三", 23));
    c.add(new Student("李四", 24));
    c.add(new Student("王五", 25));

    // forEach方法配合				匿名内部类, 其实底层也是迭代器
    c.forEach(new Consumer<Student>() {
        @Override
        public void accept(Student stu) {
            System.out.println(stu);
        }
    });

    System.out.println("------------------------");

    c.forEach(s -> System.out.println(s));


}

三个迭代器练习完整代码 :

import com.itheima.domain.Student;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.function.Consumer;

public class IteratorDemo {
    public static void main(String[] args) {

        Collection<Student> c = new ArrayList<>();

        c.add(new Student("张三", 23));
        c.add(new Student("李四", 24));
        c.add(new Student("王五", 25));

        c.forEach(new Consumer<Student>() {
            @Override
            public void accept(Student stu) {
                System.out.println(stu);
            }
        });

        System.out.println("------------------------");

        c.forEach(s -> System.out.println(s));


    }

    private static void method2(Collection<Student> c) {
        for (Student stu : c) {
            System.out.println(stu);
        }
    }

    private static void method1(Collection<Student> c) {
        // 1. 通过集合对象, 获取迭代器
        Iterator<Student> it = c.iterator();

        // Iterator<Student> it = new Itr();

        // 2. 循环判断, 集合中是否存在元素
        while (it.hasNext()) {
            // 3. 调用方法取出元素
            Student stu = it.next();   // next() : 先将元素取出来, 再将内部的指针向后移动一位
            System.out.println(stu);
        }
    }
}

List接口

图片[3]-4.0 集合-数据结构-ArrayList、LinkedList类-IT熊技术站
图片[4]-4.0 集合-数据结构-ArrayList、LinkedList类-IT熊技术站

代码演示 :

import java.util.ArrayList;
import java.util.List;

public class ListDemo {
    /*
        List接口:

            特点: 存取有序, 有索引, 可以存储重复的
                    - 因为有索引, 提供很多用索引操作元素的方法.

            注意: List接口中的集合, 因为有索引, 所以多了一种遍历方式
                    - 迭代器
                    - 增强for
                    - foreach
                    - 普通for
                	- List特有接口, ListIterator
     */
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();

        list.add("张三");
        list.add("李四");
        list.add("王五");

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

并发修改异常

  • ConcurrentModificationException
ConcurrentModificationException 并发修改异常:

           原因 : 当使用[迭代器]在遍历集合的时候, 调用了[集合对象]的添加, 或者是删除的方法, 就会出现并发修改异常
           解决方案 : 
                		就使用迭代器自己的添加或者删除方法

                		细节:
                                别除方法:Iterator里面有
                                添加方法:ListIterator迭代器里面有

问题: 那如果真的有业务场景, 需要在迭代器遍历的过程中, 删除集合元素, 怎么解决?
回答: 使用迭代器自己的删除方法

                迭代器在遍历
                迭代在在删除

问题: 需要在迭代器遍历的过程中, 添加怎么解决?
                - Iterator内部不存在添加的方法

回答: 换一个迭代器 ListIterator (List集合特有的迭代器)

--------------------------------------------------------------------------------------------------------

恶心的问题 : 迭代器在遍历的时候做删除, 如果删除的是集合的倒数第二个元素, 就没有并发修改异常
                - 原因: 略过了check方法的检测

使用List接口特有的迭代器ListIterator

public static void main(String[] args) {

    ArrayList<String> list = new ArrayList<>();

    list.add("张三");
    list.add("李四");
    list.add("王五");
    list.add("赵六");

    ListIterator<String> it = list.listIterator();

    while (it.hasNext()) {
        String s = it.next();
        if ("李四".equals(s)) {
            it.add("周七");
        }
    }

    System.out.println(list);
}

迭代器在遍历的时候做删除, 如果删除的是集合的倒数第二个元素, 就没有并发修改异常

– 原因: 略过了check方法的检测

public static void main(String[] args) {
    ArrayList<String> list = new ArrayList<>();

        list.add("abc");
        list.add("bbb");
        list.add("def");
        list.add("ccc");
        list.add("ddd");

        Iterator<String> it = list.iterator();
        while (it.hasNext()) {
            String s = it.next();
            if ("def".equals(s)) {
                it.remove();
            }
        }

        System.out.println(list);
}

Set接口

  1. 特点

其元素不可重复,使用方法基本与Collection集合一致

  1. 实现类

HashSet:由哈希表支持,对集合的迭代顺序不保证,同时没有带索引的方法,不能使用普通for循环遍历

  1. 哈希值

是JDK根据对象的地址形成的int类型的值,可通过对象的HashCode方法得到。对象类中未重写HashCode与equals方法时,不同对象哈希值不相同。若在对象中重写HashCode方法可以自定哈希值

  1. 哈希表

底层采用数组+链表实现,可以说元素是链表的数组,长度为16

存储原理:通过获得对象的哈希值对16取余,得到存储的位置,然后比较依次比较哈希值和元素内容,都不同时存入元素

  1. 注意事项

⭐若要使HashSet集合不能储存相同内容,则必须重写对象的HashCode与equals方法!!!

Map集合概述和使用

Map集合的特点

Interface Map<K,V> K:键的类型 V:值的类型

将键映射到值的对象,不包含重复的键,每个键最多只能映射一个值

当键重复时,后录入的值会替换前面的值,原理是通过Hash表实现

Map双列集合常用方法

方法名说明
Object put(Object key, Object value)以“键-值”对的方式进行存储
Object get(Object key)根据键返回相关联的值,如果不存在指定的键,返回null
Object remove(Object key)删除由指定的键映射的“键-值对”
int size( )返回元素个数
Set keySet( )返回键的集合
Collection values( )返回值的集合
boolean containsKey(Object key)如果存在由指定的键映射的“键-值对”,返回true

Map集合的两种遍历方式

使用键集合

Set<String> keys = map.keySet();
    for (String key:keys){
        String vaule = map.get(key);
        System.out.println(key+","+vaule);
    }

使用键值对对象

Set<Map.Entry<String, String>> entries = map.entrySet();
    for (Map.Entry<String, String> s:entries){
        String key = s.getKey();
        String value = s.getValue();
        System.out.println(key+","+value);
	}

注意点

⭐在HashMap集合中,若键的类型为自定义类型时,若要保证键的唯一性,必须在其类中重写HashCode与equals方法

数据结构

数据结构介绍

图片[5]-4.0 集合-数据结构-ArrayList、LinkedList类-IT熊技术站

数据结构(栈, 队列)

图片[6]-4.0 集合-数据结构-ArrayList、LinkedList类-IT熊技术站

数据结构(数组)

图片[7]-4.0 集合-数据结构-ArrayList、LinkedList类-IT熊技术站

数据结构(链表)

单链表介绍和演示

图片[8]-4.0 集合-数据结构-ArrayList、LinkedList类-IT熊技术站
图片[9]-4.0 集合-数据结构-ArrayList、LinkedList类-IT熊技术站
图片[10]-4.0 集合-数据结构-ArrayList、LinkedList类-IT熊技术站

双链表的介绍和演示

图片[11]-4.0 集合-数据结构-ArrayList、LinkedList类-IT熊技术站
图片[12]-4.0 集合-数据结构-ArrayList、LinkedList类-IT熊技术站
图片[13]-4.0 集合-数据结构-ArrayList、LinkedList类-IT熊技术站

ArrayList类、LinkedList类

ArrayList类

ArrayList类底层是基于数组实现的,根据查询元素快,增删相对慢

ArrayList长度可变原理

  • 如果只是创建了集合容器,没有进行过添加操作,底层数组默认长度为0
  • ArrayList底层是数组结构的,数组默认长度为10
  • 当数组添加满了之后,会自动扩容为1.5倍

LinkedList类

LinkedList 底层基于双链表实现的,查询元素慢,增删首尾元素是非常快的

图片[14]-4.0 集合-数据结构-ArrayList、LinkedList类-IT熊技术站

思考

LinkedList也有get方法,表面看起来是根据索引获取元素,实际上是?

回答 : 会将get方法收到的索引做if判断 , 看里头部近 , 还是尾部近 , 离谁近 , 就从哪个部分开始获取

© 版权声明
THE END
喜欢就支持一下吧
点赞0赞赏 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容