Java基础

1:数据结构

        1:栈和队列的区别,具体的场景应用

        栈(Stack)和队列(Queue)是两种基本的数据结构,它们在数据的存取顺序不同;

        栈,后进先出:最后进入栈的元素最先被移出。

        队列,先进先出:第一个进入队列的元素最先被移出。

        2:set 的去重机制

        HashSet 去重机制

        HashSet 是基于哈希表(Hash Table)实现的,它通过元素的 哈希值(hash         code)  equals() 方法来确定元素的唯一性。

        TreeSet 去重机制

        TreeSet 是基于红黑树(Red-Black Tree)实现的,它通过元素的 

        自然顺序  自定义比 较器 来保证集合的有序性和唯一性。

        3:HashMap 的实现原理

        基本结构: 数组 + 链表/红黑树

        存储原理:

        当往 HashMap 中存储一个键值对时,

        HashMap 首先会根据键的哈希值(hash code)计算出该键值对在数组中的存储位置

        如果不同的键有相同的哈希值(即发生了 哈希冲突)

        HashMap 会将这些键值对存储在同一个位置(即同一个桶)中,通过链表或红黑树来管理。

        哈希函数:

        HashMap 通过键的 hashCode() 方法生成键的哈希值

        并通过一个哈希函数将哈希值转换为数组的索引。

        计算数组索引的公式:index = (n - 1) & hash,其中 n 是数组的长度。

        使用按位与操作 (&) 来对哈希值进行限制,使得索引值总是落在数组的有效范围内。

        插入操作

        计算哈希值,确定数组索引,检查哈希冲突,如果该位置为空,则将键值对放入该位置。

        如果该位置已经有其他键值对(即发生哈希冲突),

        HashMap 会遍历该位置的链表或红黑树,检查是否已经有相同的键:

        如果有相同的键,则更新对应的值。

        如果没有相同的键,则将新的键值对添加到链表或树的末尾。

        链表到红黑树的转换

        当同一个位置的链表长度超过 8 时(默认值),HashMap 会将链表转换为 红黑树

        如果链表长度小于 6,会从红黑树转换回链表

        查找操作

        HashMap 的查找操作是通过键的哈希值来定位对应的数组位置,从而查找值的。

        查找步骤如下:

        通过键的 hashCode() 计算哈希值。

        通过哈希值和数组长度计算出对应的数组索引。

        在该数组索引处检查是否有链表或红黑树:

        如果没有,则返回 null。

        如果有,则根据链表或红黑树的结构找到对应的键,并返回相应的值。

        扩容机制

        HashMap 的数组在插入大量键值对时可能会装满,这时需要对数组进行 扩容。

        HashMap 的扩容机制是通过重新分配更大的数组,

        并将原数组中的元素重新哈希并插入到新数组中。

        触发扩容的条件:

        当 HashMap 中的元素数量超过 阈值 时,触发扩容。

        阈值的计算:阈值 = 数组长度 * 负载因子,默认负载因子为 0.75。

        扩容过程:

        创建一个新数组,长度是原数组的 2 倍。

        将原数组中的所有键值对重新计算哈希值,并插入到新数组中。

        如果某个位置有链表或红黑树,则重新计算每个键的数组索引,

        重新分配到新数组的不同位置。

        删除操作

        删除操作也是通过键的哈希值定位到数组中的具体位置。

        删除步骤如下:

        通过键的 hashCode() 计算哈希值。

        根据哈希值定位到数组的具体索引。

        遍历该位置的链表或红黑树,找到对应的键并移除该节点。

        如果是红黑树,还需要进行树的调整。

4HashMap Hashtable 区别

        1. 线程安全性

        HashMap:非线程安全。它不支持多个线程同时访问和修改同一个 HashMap,如果有多线程并发访问,必须通过外部同步机制(如 Collections.synchronizedMap() 或 ConcurrentHashMap)来保证线程安全。

        Hashtable:线程安全。Hashtable 的所有方法都使用了 synchronized 关键字进行同步。

        2. 性能

        HashMap:由于没有内置的同步机制,HashMap 的性能一般比 Hashtable 要高

        3. 是否允许 null 键和值

        HashMap:允许 1 个 null 键 和 多个 null 值

        Hashtable:不允许 null 键或 null 值

        4. 扩容机制

        HashMap:默认初始容量为 16,负载因子为 0.75,以 2 倍扩容

        Hashtable:默认初始容量为 11,负载因子为 0.75,以 2 倍加 1扩容

2:线程

        1. 什么是线程和进程?

        进程:是指一个在内存中运行的应用程序,常见的app都是一个个进程。进程具有自己独立的内存空间,一个进程可以有多个线程;

        线程:是指进程中的一个执行任务的单元,负责执行当前进程中程序的执行,一个进程至少有一个线程,一个进程内的多个线程见可共享数据

        2:创建线程的几种方式?

        实现Runnable接口

        继承Thread类

        实现Callable接口

        使用Executors工具类创建线程池

        3:Java线程状态和方法?

        Java线程状态有6种,分别是 NEW(新建状态)、RUNNABLE(就绪状态)、 BLOCKED(阻塞状态)、WAIT(等待状态)、TIME_WAIT(超时等待状态)、TERMINATED(终止状态):

        4:sleep()和wait()方法的区别是什么?

        虽然两个方法都有让线程暂停的作用,但是两个还是发挥不同作用的:

        wait()是Object类的方法,sleep()是Thread类的方法;

        wait()释放锁,让线程进入等待状态,sleep()不释放锁,让线程进入阻塞状态;

        wait()方法后线程不会自动恢复执行,需要手动调用notify()/notifyAll()方法唤醒,sleep()在睡眠固定时间后会走动苏醒;

        wait()常用于线程间交互/通信,sleep通常被用于暂停等待

        5:并发编程的三要素是什么?

        原子性:原子是指一个不可再分割的颗粒,原子性值得是一个或者多个操作要么全部成功要么全部失败;

        可见性:一个线程对贡献变量的修改,另一个线程能够立刻看到(volatile,synchronized);

        有序性:程序执行代码的顺序要按照代码的先后顺序执行。

        6:形成死锁的四个必要条件:

        互斥条件:线程申请的资源在一段时间中只能被一个线程使用

        请求与等待条件:线程已经拥有了一个资源,但是又申请新的资源,拥有的资源保持不变 。

        不可剥夺条件:在一个线程没有用完,主动释放资源的时候,不能被抢占。

        循环等待条件:多个线程之间存在资源循环链。

        7:线程池的拒绝策略?

        当任务队列和线程池都满了时所采取的应对策略:

        默认是AbordPolicy,表示无法处理新任务,并抛出RejectedExecutionException异常;

        CallerRunsPolicy:用调用者所在的线程处理任务。此策略提供简单的反馈机制,能够减缓新任务的提交速度;

        DiscardPolicy:不能执行任务,并将任务删除;

        DiscardOldestPolicy:丢弃队列最近的任务,并执行当前的任务。

        8:Synchronization lock都是悲观锁,适合写操作比较多的情况

        乐观锁CAS算法,其实就是使用当前线程副本数据跟内存数据对比,然后再去操作或者去重试

        原子类就是CAS

        CompareAndSet底层就是调用CompareAndSwap,不推荐CompareAndSwap,因为他是unsafe,不受jvm 管理,需要自己释放内存

        CAS会引入ABA问题,原子类加标记

        volatile 关键字,可见性和排序行,防止CPU出现指令重排,懒汉单例模式就是volatile 修饰,加锁双重判断

 

3IO

 

        1.什么是Java NIO?

        Java NIO : 同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。

 

4:设计模式

        1:单例模式:

        单例模式整个系统有一个对象实例。

        优点:不会频繁地创建和销毁对象,浪费系统资源。

        使用场景:IO 、数据库连接、Redis 连接等。

        静态加载单例模式代码实现:

        

        单例模式的延迟加载,非线程安全

        

        单例模式的线程安全代码

        

        

        2:工厂模式

        建立一个工厂类,对实现了同一接口的一些类进行实例的创建

        3:策略模式

        策略模式是指定义一系列算法,将每个算法都封装起来,并且使他们之间可以相互替换。

        4:观察者模式

        观察者模式是定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新

        5:代理模式

        JDK动态代理

        基于接口

        反射机制 InvocationHandler.invoke()

        CGLIB动态代理

        基于字节码操作

        生成目标类的子类并重写目标类的方法来实现代理

        优缺点

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值