Java-进阶知识

本文详细介绍了Java集合框架中的Collection集合,包括ArrayList和LinkedList的底层原理、遍历方式(迭代器、foreach、lambda表达式)以及泛型的深入应用。同时,探讨了常见数据结构如栈、队列、数组、链表、二叉树等的特点和应用场景,最后讨论了集合的并发修改异常问题及解决方案。
摘要由CSDN通过智能技术生成

目录

一、集合概述

二、Collection集合的体系特点

三、Collection集合常用API

四、Collection集合的遍历方式

1.方式一:迭代器

2.方式二:foreach/增强for循环

3.方式三:lambda表达式

五、Collection集合存储自定义类型的对象

六、常见数据结构

1.数据结构概述、栈、队列

2.数组

3.链表

4.二叉树、二叉查找树

5.平衡二叉树

6.红黑树

七、List系列集合

1.List集合特点、特有API

2.List集合的遍历方式小结

3.ArrayList集合的底层原理

 4.LinkedList集合的底层原理

 八、补充知识:集合的并发修改异常问题

九、泛型深入

1.泛型的概述和优势

2.自定义泛型类

3.自定义泛型方法

4.自定义泛型接口

5.泛型通配符、上下限


一、集合概述

集合和数组都是容器。

数组的特点:1.数组定于完成并启动后,类型确定、长度固定;2.在进行增删数据操作的时候,数组是不太合适的,增删数据都要放弃原数组或者移位

数组适合的场景:当业务数据的个数是固定的,且是同一批数据类型的时候,可以采取定义数组存储

集合的特点:1.集合的大小不固定,启动后可以动态变化,类型也可以选择不固定,集合更像气球;2.集合非常适合做元素的增删操作

集合适用的场景:数据的个数不确定,需要进行增删元素的时候

二、Collection集合的体系特点

 Collection单列集合,每个元素(数据)只包含一个值。

Map双列集合,每个元素包含两个值(键值对)。

 Collection集合特点:

List系列集合:添加的元素是有序、可重复、有索引;

ArrayList、LinkedList:有序、可重复、有索引。

Set系列集合:添加的元素是无序、不重复、无索引;

HashSet:无序、不重复、无索引;LinkedHashSet:有序、不重复、无索引;TreeSet:按照大小默认升序排序、不重复、无索引。

集合对泛型的支持:集合都是支持泛型的,可以在编译阶段约束集合只能操作某种数据类型

三、Collection集合常用API

Collection是单列集合的祖宗接口,它的功能是全部单列集合都可以继承使用的。

package com.pikaqiu.d2_collection_api;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Objects;

public class CollectionDemo {
    public static void main(String[] args) {
        Collection<String> c = new ArrayList<>();
        //1.添加元素,添加成功返回true
        c.add("Java");
        c.add("HTML");
        System.out.println(c.add("HTML")); //true
        c.add("Mysql");
        c.add("Java");
        System.out.println(c);

//        //2.清空集合的元素
//        c.clear();
//        System.out.println(c);

        //3.判断集合是否为空,是空就返回true,反之false
        System.out.println(c.isEmpty()); //false

        //4.获取集合大小
        System.out.println(c.size());

        //5.判断集合中是否包含某个元素
        System.out.println(c.contains("Java")); //true
        System.out.println(c.contains("java")); //false

        //6.删除某个元素:如果有多个重复的元素默认删除前面的第一个
        System.out.println(c.remove("Java")); //true
        System.out.println(c); //[HTML, HTML, Mysql, Java]

        //7.把集合转换成数组
        Object[] arrs = c.toArray();
        System.out.println(Arrays.toString(arrs));

        System.out.println("-------------------------------");
        //拓展:合并两个集合
        Collection<String> c1 = new ArrayList<>();
        c1.add("java1");
        c1.add("java2");
        Collection<String> c2 = new ArrayList<>();
        c2.add("赵敏");
        c2.add("殷素素");
        c1.addAll(c2);
        System.out.println(c1); //[java1, java2, 赵敏, 殷素素]
        System.out.println(c2); //[赵敏, 殷素素]
    }
}

四、Collection集合的遍历方式

1.方式一:迭代器

迭代器遍历概述:遍历就是一个一个把容器中的元素访问一遍;迭代器在Java中的代表就是Iterator,迭代器是集合的专用遍历方式

package com.pikaqiu.d3_collection_traversal;

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

public class CollectionDemo1 {
    public static void main(String[] args) {
        Collection<String> lists = new ArrayList<>();
        lists.add("赵敏");
        lists.add("小昭");
        lists.add("素素");
        lists.add("灭绝");
        System.out.println(lists);

        //1.得到当前集合的迭代器对象
        Iterator<String> it =  lists.iterator();
//        for (int i = 0 ; i < lists.size() ; i++) {
//            String ele = it.next();
//            System.out.print(ele + " ");
//        }

        //定义while循环
        while (it.hasNext()){
            String ele = it.next();
            System.out.print(ele + " ");
        }
    }
}

2.方式二:foreach/增强for循环

增强for循环:既可以遍历集合也可以遍历数组;JDK5之后出现的,其内部原理是一个Iterator迭代器,遍历集合相当于迭代器的简化写法;实现Iterable接口类才可以使用迭代器和增强for,Collection接口已经实现了Iterable接口

格式:for(元素数据类型 变量名 : 数组或者Collection集合){//在此处使用变量即可,该变量就是元素}

package com.pikaqiu.d3_collection_traversal;

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

public class CollectionDemo2 {
    public static void main(String[] args) {
        Collection<String> lists = new ArrayList<>();
        lists.add("赵敏");
        lists.add("小昭");
        lists.add("素素");
        lists.add("灭绝");
        System.out.println(lists);

        for(String ele : lists){
            System.out.print(ele + " ");
        }
    }
}

3.方式三:lambda表达式

得益于JDK8开始的新技术Lambda表达式,提供了一种更简单、更直接的遍历集合的方式

package com.pikaqiu.d3_collection_traversal;

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

public class CollectionDemo3 {
    public static void main(String[] args) {
        Collection<String> lists = new ArrayList<>();
        lists.add("赵敏");
        lists.add("小昭");
        lists.add("素素");
        lists.add("灭绝");
        System.out.println(lists);

        lists.forEach(s -> System.out.print(s + " "));
        System.out.println();

        lists.forEach(System.out::println);
    }
}

五、Collection集合存储自定义类型的对象

package com.pikaqiu.d4_collection_object;

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

public class TestDemo {
    public static void main(String[] args) {
        //定义电影类,这里省略
        //2.定义一个集合对象存储三部电影的信息
        Collection<Movie> movies = new ArrayList<>();
        movies.add(new Movie("《你好,李焕英》",9.5,"贾玲、张小斐"));
        movies.add(new Movie("《唐人街探案》",8.8,"王宝强、刘昊然"));
        movies.add(new Movie("《刺杀小说家》",8.5,"杨幂、雷佳音"));

        //3.遍历
        for(Movie movie : movies){
            System.out.println("电影:" + movie.getName());
            System.out.println("评分:" + movie.getScore());
            System.out.println("主演:" + movie.getActor());
        }
    }
}

六、常见数据结构

1.数据结构概述、栈、队列

数据结构概述:数据结构是计算机底层存储、组织数据的方式。是指数据相互之间是什么方式排列在一起的;一般情况下,精心选择的数据结构可以带来更高的运行或者存储效率。

栈:先进后出

数据进栈:压栈(进栈)

数据出栈:弹栈(出栈)

队列:先进先出

数据从后端进入队列:入队

数据从前端出队列:出队

2.数组

查询速度快:查询数据通过地址值和索引定位,查询任意数据耗时相同(元素在内存中是连续存储的)

删除效率低:要将原数据删除,同时后面每个数据前移

添加效率低:添加位置后的每个数据后移,再添加元素

3.链表

链表的特点:链表的元素再内存中是不连续存储的,每个元素节点都包含数据值和下一个元素的地址

链表查询慢:无论哪个数据都要从头开始找

链表的增删相对较快,不用移动其他元素的位置

4.二叉树、二叉查找树

二叉树的特点:1.只能有一个根节点,每个节点最多支持2个直接节点;节点的度:节点拥有的子树的个数,二叉树的度不大于2,叶子节点度为0的节点,也称之为终端结点;3.高度:叶子结点的高度为1,叶子结点的父亲结点的高度为2,依次类推,根节点的高度最高;4.层:跟结点在第一层,以此类推;5.兄弟节点:拥有共同父亲节点的节点互称为兄弟节点

二叉查找树又称二叉排序树或者二叉搜索树。

二叉查找树的特点:1.每个节点最多两个子节点;2.左子树所有节点的值都小于根节点的值;3.右子树所有节点的值都大于根节点的值

5.平衡二叉树

二叉树查找的问题:出现瘸子现象。导致查询的性能与单链表一样,查询速度变慢

平衡二叉树:在满足查找二叉树的前提下,让树尽可能矮小,以此提高查数据的性能

平衡二叉树的要求:任意节点的左右两个子树的高度差不超过1,任意节点的左右子树都是一棵平衡二叉树

6.红黑树

红黑树概述:1.红黑树是一种平衡的二叉查找树,是计算机中用到的一种数据结构;2.1972年出现,当时被称为平衡二叉B树,1978年被修改为如今的"红黑树";3.每一个节点可以是红或黑,红黑树不是通过高度平衡的,它的平衡是通过"红黑规则"进行实现的

红黑规则:1.每个节点或是红色,或者是黑色的,根节点必须是黑色的;2.如果一个节点没有子节点或者父节点,则该节点相应的指针属性为Nil,这些Nil视为叶节点,叶节点是黑色的;3.如果一个节点是红色,那么它的子节点必须是黑色(不能出现两个红节点相连的情况);4.对每一个节点,从该节点到其所有后代节点的简单路径上,均包含相同的数目的黑色节点

七、List系列集合

1.List集合特点、特有API

ArrayList、LinkedList:有序、可重复、有索引

有序:存储和取出元素顺序一致;有索引:可以通过索引操作元素;可重复:存储的元素可以重复

2.List集合的遍历方式小结

1.for循环;2.迭代器;3.增强for;4.lambda表达式

3.ArrayList集合的底层原理

ArrayList集合的底层原理:1.ArrayList底层是基于数组实现的:根据索引定位元素块,增删需要做元素的移位操作;2.第一次创建集合并添加第一个元素的时候,在底层创建一个默认长度为10的数组

 4.LinkedList集合的底层原理

LinkedList的特点:底层数据结构是双链表,查询慢,首尾操作的速度是极快的,所以多了很多首尾操作的特有API

 八、补充知识:集合的并发修改异常问题

package com.pikaqiu.d6_collection_update_delete;

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

public class Test {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("黑马");
        list.add("Java");
        list.add("Java");
        list.add("赵敏");
        list.add("赵敏");
        list.add("素素");
        System.out.println(list); //[黑马, Java, Java, 赵敏, 赵敏, 素素]

        //1.迭代器遍历删除
//        Iterator<String> it = list.iterator();
//        while(it.hasNext()){
//            String ele = it.next();
//            if("Java".equals(ele)){
//                //list.remove("Java");
//                it.remove(); //删除当前元素,并且不会后移
//            }
//        }
//        System.out.println(list);

        //foreach遍历删除元素
        //解决不了这个问题
//        System.out.println("---------------------------------");
//        for (String s : list) {
//            if("Java".equals(s)){
//                list.remove("Java");
//            }
//        }
//        System.out.println(list);

        //lambda表达式遍历删除
        //同foreach一样
//        list.forEach(s -> {
//            if("Java".equals(s)){
//                list.remove("Java");
//            }
//        });

        //for循环(不出现异常错误,但是会漏掉元素)
//        for (int i = 0; i < list.size(); i++) {
//            String ele = list.get(i);
//            if("Java".equals(ele)){
//                list.remove("Java");
//            }
//        }
//        System.out.println(list);
        
        //后删操作即可
        for (int i = list.size() - 1; i >= 0; i--) {
            String ele = list.get(i);
            if("Java".equals(ele)){
                list.remove("Java");
            }
        }
        System.out.println(list);
    }
}

九、泛型深入

1.泛型的概述和优势

泛型概述:JDK5中开始引入的特性,可以在编译阶段约束操作的数据类型,并进行检查

泛型格式:<数据类型>; 

注意:泛型只支持引用类型

集合体系的全部接口和实现类都是支持泛型的使用的

泛型的好处:1.统一数据类型;2.把运行时期的问题提前到了编译期间,避免了强制类型转换可能出现的异常,因为编译阶段类型就能确定下来

2.自定义泛型类

泛型类的概述:1.定义类时同时定义了泛型的类就是泛型类;2.泛型类的格式:修饰符 class 类名<泛型变量>{ }

作用:编译阶段可以指定数据类型,类似于集合的作用

泛型类的原理:把出现的泛型变量的地方全部替换成传输的真实数据类型

package com.pikaqiu.d8_genericity_class;

import java.util.ArrayList;

public class MyArrayList<E> {
    private ArrayList lists = new ArrayList();

    public void add(E e){
        lists.add(e);
    }

    public void remove(E e){
        lists.remove(e);
    }

    @Override
    public String toString(){
        return lists.toString();
    }
}

package com.pikaqiu.d8_genericity_class;

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        MyArrayList<String> list = new MyArrayList<>();
        list.add("Java");
        list.add("Java");
        //list.add(22);
        list.add("Mysql");
        list.add("Mysql");
        System.out.println(list);

        list.remove("Java");
        System.out.println(list);
    }
}

3.自定义泛型方法

定义方法的同时定义了泛型的方法就是泛型方法

泛型方法的格式:修饰符 <泛型变量> 方法返回值 方法名称(形参列表){ }

泛型方法的原理:把出现泛型变量的地方全部替换成传输的真实数据类型

package com.pikaqiu.d9_genericity_method;

public class Test {
    public static void main(String[] args) {
        String[] names = {"嘿嘿","哈哈","嗯哼"};
        printArray(names);
        Integer[] ages = {18,19,20};
        printArray(ages);
    }

    public static <T> void printArray(T[] arr){
        if(arr != null){
            StringBuilder sb = new StringBuilder("[");
            for (int i = 0 ; i < arr.length ; i++) {
                sb.append(arr[i]).append(i == arr.length - 1 ? "" : ", ");
            }
            sb.append("]");
            System.out.println(sb);
        }else {
            System.out.println(arr);
        }
    }
}

4.自定义泛型接口

概述:使用了泛型定义的接口就是泛型接口;

泛型接口的格式:修饰符 interface Data<E>{ }

作用:泛型接口可以让实现类选择当前功能需求操作的数据类型

泛型接口的原理:实现类可以实现接口的时候传入自己操作的数据类型,这样重写的方法都将是针对于该类型的操作

5.泛型通配符、上下限

通配符: ? 

?可以在"使用泛型"的时候代表一切类型

泛型的上下限:1.?extends Car: ?必须是Car或者其子类 泛型上限;2. ? super Car:?必须是Car或者其父类 泛型下限

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

皮卡丘√

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值