java-题库

article/2025/10/1 14:07:39

java-题库

  • 一、hashMap的底层实现
    • 1.1、hashMap概述
    • 1.2、JDK1.7-扩容源码
    • 1.3、JDK1.7链表迁移过程
    • 1.4、JDK1.8下的扩容机制
  • 二、java面向对象的三大特征
  • 三、JVM相关
  • 四、集合相关
  • 五、JDK1.8新特性
    • 5.1、接口内可以添加非抽象的方法实现
    • 5.2、Lambda表达式
    • 5.3、函数式接口
    • 5.4、Stream API
    • 5.6、引入了ForkJoin框架
    • 5.7、引入了新的日期API LocalDate | LocalTime | LocalDateTime
  • 六、抽象类和接口的区别
  • 七、==和eques区别

一、hashMap的底层实现

1.1、hashMap概述

  • HashMap基于Map接口实现,键值对存储,允许使用null 建和null值。
  • HashMap无序的,HashMap线程不安全。

1.2、JDK1.7-扩容源码

public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable { //......// 扩容方法void resize(int newCapacity) {// 1、创建临时变量,将HashMap数组数据赋值给新数组作临时存储Entry[] oldTable = table;// 2、判断老数组长度是否超过了允许的最大长度,最大长度为 1 << 30int oldCapacity = oldTable.length;if (oldCapacity == MAXIMUM_CAPACITY) {threshold = Integer.MAX_VALUE;return;}// 3、创建新的Entry数组,并扩容Entry[] newTable = new Entry[newCapacity];// 4、扩容赋值,即将老数组中的数据赋值到新数组中// initHashSeedAsNeeded(newCapacity) 得到的是一个hash的随机值(哈希种子),在计算哈希码时会用到这个种子,作用是减少哈希碰撞transfer(newTable, initHashSeedAsNeeded(newCapacity));// 6、扩容后赋值table = newTable;threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);}// newTable : 表示新数组,即扩容后创建的新数组// rehash : 是否需要重新计算哈希值void transfer(Entry[] newTable, boolean rehash) {int newCapacity = newTable.length;// 5、将老map中的数据赋值到新map中(数组和链表复制迁移)for (Entry<K,V> e : table) {   while(null != e) {Entry<K,V> next = e.next;if (rehash) {e.hash = null == e.key ? 0 :hash(e.key);}// 计算Entry元素在Entry[]数组中的位置int i = indexFor(e.hash, newCapacity);// 链表头插法赋值过程e.next = newTable[i];newTable[i] = e;e = next;}}}//......}

1.3、JDK1.7链表迁移过程

  • 主要的代码
	e.next = newTable[i];newTable[i] = e;e = next;
  • 假设HashMap的存储状态如下
    在这里插入图片描述
  • 第一次处理e
    //将e的next置为nulle.next = newTable[i]  
​ 	对oldTable进行遍历的过程中,取出元素e,假设先取出图中的元素e,
在执行这行代码时,相当于断开x位置e与e1的链表关系,并与newTable[i]建立链表关系,
此时newTable[i]位置为null//将e的赋值给,新数组newTable[i] newTable[i] = e此时将oldTable中的e复制到newTable中的i位置,同时链表e指向null

在这里插入图片描述

  • 第二次处理e1
while(null != e) {// 这里已经将e.next存储为一个临时变量,也就是e1和e2形成的链表Entry<K,V> next = e.next;if (rehash) {e.hash = null == e.key ? 0 :hash(e.key);}......
}		
  // 此时为 e1,组成的链表Entry<K,V> next = e.next;//再进行一次遍历分析,而这次遍历分析从e1开始 即e1.nexte.next = newTable[i]//此为enewTable[i] = e//此e为e1,他的nect 挂的e,//即 newTable[i]的第一个元素为e1 

在这里插入图片描述

  • 第n次处理后
链表顺序:开始为e-->e1-->e2
完成扩容后:e2-->e1-->e

在这里插入图片描述

1.4、JDK1.8下的扩容机制

  • 底层实现由之前的 “数组+链表” 改为 “数组+链表+红黑树”。
  • 当链表节点较少时仍然是以链表存在,当链表节点较多时(大于8)且数组的长度大于64,时会转为红黑树
    public V put(K key, V value) {return putVal(hash(key), key, value, false, true);}/*** put()方法真正逻辑所在** @param hash key的hash值* @param key key* @param value value值* @param onlyIfAbsent true表示不更新现有值* @param evict 如果为false,则表处于创建模式。HashMap中暂未使用*/final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {// tab 哈希数组,p 该哈希桶的首节点,n hashMap的长度,i 计算出的数组下标Node<K,V>[] tab; Node<K,V> p; int n, i;// 如果数组还没初始化,进行数组初始化。使用懒加载机制,table一开始是没有加载的,等put后才开始加载if ((tab = table) == null || (n = tab.length) == 0)n = (tab = resize()).length;// 如果根据key计算出的数组位置没有数据if ((p = tab[i = (n - 1) & hash]) == null)// 新建一个Node节点插入到相应数据位置。tab[i] = newNode(hash, key, value, null);// key的hash值对应的数组下标位置不为空的情况else {// e 临时节点 ,k 当前节点的keyNode<K,V> e; K k;//第一种,数组hash槽首节点的key与当前节点的相等,将当前节点赋值给临时节点e = pif (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))e = p;// hash槽的数据结构为红黑树else if (p instanceof TreeNode)// 在红黑树中进行添加,如果该节点已经存在,则返回该节点(不为null),用与判断put操作是否成功,如果添加成功返回nulle = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);// 链表节点else {// 遍历链表for (int binCount = 0; ; ++binCount) {// 如果在链表尾部还没有找到当前key值,则在链表尾部新增节点if ((e = p.next) == null) {p.next = newNode(hash, key, value, null);// 判断是否转红黑树if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1sttreeifyBin(tab, hash);break;}//如果链表中有重复的key,e则为当前重复的节点,并结束链表的循环遍历if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))break;p = e;}}// 如果key值以前已经存在,则对value进行覆盖,并返回value的旧值。if (e != null) {V oldValue = e.value;if (!onlyIfAbsent || oldValue == null)e.value = value;// 将红黑树的root节点放到链表队首,并将root Node存储在table数组中。afterNodeAccess(e);return oldValue;}}// 走到这说明新增了一个Node节点,对Map的修改次数进行+1++modCount;// Map的元素容量+1,如果大于扩容阈值,进行扩容if (++size > threshold)resize();// 模板方法,后置处理器afterNodeInsertion(evict);return null;}

在这里插入图片描述

二、java面向对象的三大特征

1、封装:属性私有化,提供setter和getter方法
2、继承:继承是指将多个相同的属性和方法提取出来,新建一个父类
3、多态:分为两种:设计时多态、运行时多态

三、JVM相关

四、集合相关

第一代线程安全集合类Vector. Hashtable是怎么保证线程安排的:使用synchronized修饰方法缺点:效率低下第二代线程非安全集合类ArrayList, HashMap线程不安全,但是性能好,用来替代VectorHashtable使用ArrayListHashMap,需要线程安全怎么办呢?使用 Collections.synchronizedList(list); Collections.synchronizedMap(m);第三代线程安全集合类在大量并发情况下如何提高集合的效率和安全呢?java.utll.concurrent.*ConcurrentHashMap:CopyOnWriteArrayList :CopyOnWriteArraySet: 注意不是 CopyOnWriteHashSet*底层大都采用Lock(1.8ConcurrentHashMap不使用LocktW ,保证安全的同时,性能也很高.

五、JDK1.8新特性

5.1、接口内可以添加非抽象的方法实现

	java 8允许我们给接口添加一个非抽象的方法实现,只需要使用ddefault关键字即
可,这个特征又叫做犷展方法,代码如下:interface Formula {double calculatefint a);default double sqrt(int a) {return Math.sqrt(a);}}Formula接口在拥有calculate方法之外同时还定义了sqrt方法,实现了Formula接口的子类
只需要实现calculate方法,默认方法sqrl将在子类上可以直接使用.

5.2、Lambda表达式

Lambda 规定接口中只能有一个需要被实现的方法。

5.3、函数式接口

  • 函数式接口的提出是为了给Lambda表达式的使用提供更好的支持。
  • 简单来说就是只定义了一个抽象方法的接口(Object类的public方法除外),就是函数式接口,并且还提供了注解@FunctionalInterface

5.4、Stream API

  • Stream操作的三个步骤:创建stream,中间操作,终止操作
  • 创建stream
    // 1,校验通过Collection 系列集合提供的stream()或者paralleStream()List<String> list = new ArrayList<>();Strean<String> stream1 = list.stream();// 2.通过Arrays的静态方法stream()获取数组流String[] str = new String[10];Stream<String> stream2 = Arrays.stream(str);// 3.通过Stream类中的静态方法ofStream<String> stream3 = Stream.of("aa","bb","cc");// 4.创建无限流// 迭代Stream<Integer> stream4 = Stream.iterate(0,(x) -> x+2);//生成Stream.generate(() ->Math.random());
  • 中间操作(过滤、map)
/*** 筛选 过滤  去重*/emps.stream().filter(e -> e.getAge() > 10).limit(4).skip(4)// 需要流中的元素重写hashCode和equals方法.distinct().forEach(System.out::println);/***  生成新的流 通过map映射*/emps.stream().map((e) -> e.getAge()).forEach(System.out::println);/***  自然排序  定制排序*/emps.stream().sorted((e1 ,e2) -> {if (e1.getAge().equals(e2.getAge())){return e1.getName().compareTo(e2.getName());} else{return e1.getAge().compareTo(e2.getAge());}}).forEach(System.out::println);
  • 终止操作
 /***      查找和匹配*          allMatch-检查是否匹配所有元素*          anyMatch-检查是否至少匹配一个元素*          noneMatch-检查是否没有匹配所有元素*          findFirst-返回第一个元素*          findAny-返回当前流中的任意元素*          count-返回流中元素的总个数*          max-返回流中最大值*          min-返回流中最小值*//***  检查是否匹配元素*/boolean b1 = emps.stream().allMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));System.out.println(b1);boolean b2 = emps.stream().anyMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));System.out.println(b2);boolean b3 = emps.stream().noneMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));System.out.println(b3);Optional<Employee> opt = emps.stream().findFirst();System.out.println(opt.get());// 并行流Optional<Employee> opt2 = emps.parallelStream().findAny();System.out.println(opt2.get());long count = emps.stream().count();System.out.println(count);Optional<Employee> max = emps.stream().max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));System.out.println(max.get());Optional<Employee> min = emps.stream().min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));System.out.println(min.get());

5.6、引入了ForkJoin框架

  • 就是在必要的情况下,将一个大任务,进行拆分(fork)成若干个小任务(拆到不可再拆时),再将一个个的小任务运算的结果进行 join 汇总
/*** 要想使用Fark—Join,类必须继承* RecursiveAction(无返回值)* Or* RecursiveTask(有返回值)
*
*/
public class ForkJoin extends RecursiveTask<Long> {/*** 要想使用Fark—Join,类必须继承RecursiveAction(无返回值) 或者* RecursiveTask(有返回值)** @author Wuyouxin*/private static final long serialVersionUID = 23423422L;private long start;private long end;public ForkJoin() {}public ForkJoin(long start, long end) {this.start = start;this.end = end;}// 定义阙值private static final long THRESHOLD = 10000L;@Overrideprotected Long compute() {if (end - start <= THRESHOLD) {long sum = 0;for (long i = start; i < end; i++) {sum += i;}return sum;} else {long middle = (end - start) / 2;ForkJoin left = new ForkJoin(start, middle);//拆分子任务,压入线程队列left.fork();ForkJoin right = new ForkJoin(middle + 1, end);right.fork();//合并并返回return left.join() + right.join();}}/*** 实现数的累加*/@Testpublic void test1() {//开始时间Instant start = Instant.now();//这里需要一个线程池的支持ForkJoinPool pool = new ForkJoinPool();ForkJoinTask<Long> task = new ForkJoin(0L, 10000000000L);// 没有返回值     pool.execute();// 有返回值long sum = pool.invoke(task);//结束时间Instant end = Instant.now();System.out.println(Duration.between(start, end).getSeconds());}/*** java8 并行流 parallel()*/@Testpublic void test2() {//开始时间Instant start = Instant.now();// 并行流计算    累加求和LongStream.rangeClosed(0, 10000000000L).parallel().reduce(0, Long :: sum);//结束时间Instant end = Instant.now();System.out.println(Duration.between(start, end).getSeconds());}@Testpublic void test3(){List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);list.stream().forEach(System.out::print);list.parallelStream().forEach(System.out::print);}

5.7、引入了新的日期API LocalDate | LocalTime | LocalDateTime

  • LocalDateTime
    @Testpublic void test(){// 从默认时区的系统时钟获取当前的日期时间。不用考虑时区差LocalDateTime date = LocalDateTime.now();//2018-07-15T14:22:39.759System.out.println(date);System.out.println(date.getYear());System.out.println(date.getMonthValue());System.out.println(date.getDayOfMonth());System.out.println(date.getHour());System.out.println(date.getMinute());System.out.println(date.getSecond());System.out.println(date.getNano());// 手动创建一个LocalDateTime实例LocalDateTime date2 = LocalDateTime.of(2017, 12, 17, 9, 31, 31, 31);System.out.println(date2);// 进行加操作,得到新的日期实例LocalDateTime date3 = date2.plusDays(12);System.out.println(date3);// 进行减操作,得到新的日期实例LocalDateTime date4 = date3.minusYears(2);System.out.println(date4);}
  • LocalDate
 //获取当前日期,只含年月日 固定格式 yyyy-MM-dd    2018-05-04LocalDate today = LocalDate.now();// 根据年月日取日期,5月就是5,LocalDate oldDate = LocalDate.of(2018, 5, 1);// 根据字符串取:默认格式yyyy-MM-dd,02不能写成2LocalDate yesteday = LocalDate.parse("2018-05-03");// 如果不是闰年 传入29号也会报错LocalDate.parse("2018-02-28");

六、抽象类和接口的区别

  • 描述特征用接口
  • 描述概念用抽象类

七、==和eques区别

	==号在比较基本数据类型时比较的是值,而用==号比较两个对象时比较的是两个对象的地址值。
  • equals()方法存在于Object类中,因为Object类是所有类的直接或间接父类,也就是说所有的类中的equals()方法都继承自Object类,而通过源码我们发现,Object类中equals()方法底层依赖的是==号,那么,在所有没有重写equals()方法的类中,调用equals()方法其实和使用==号的效果一样,也是比较的地址值,然而,Java提供的所有类中,绝大多数类都重写了equals()方法,重写后的equals()方法一般都是比较两个对象的值.

http://chatgpt.dhexx.cn/article/iLb9jiLL.shtml

相关文章

Java二级考试题库

1、 2、 3、 4、 5、 6、 7、 8、 9、 10、 11、 12、 13、 14、 15、 16、 17、 18、 19、 20、 21、 22、 23、 24、 25、 26、 27、 注意&#xff1a;&#xff08;1&#xff09;基本型数据变量传递的是数值&#xff0c;修改会直接影响数据&#xff1b;而引用型变量传递的是…

java基础_题库详解

删除线格式 # 1 JDK和JRE有什么区别&#xff1f; JRE&#xff1a;Java Runtime Environment&#xff08; java 运行时环境&#xff09;。即java程序的运行时环境&#xff0c;包含了 java 虚拟机&#xff0c;java基础类库。 JDK&#xff1a;Java Development Kit&#xff08; ja…

Java笔试题

随机从1到100000中间随机取出100个不同的质数&#xff0c;然后按从小到大的顺序排列 public class IsPrime { //工具类// 输入一个数,判断是否为质数,费时方法public static Integer isPrime(int num) {if (num 0 || num 1)return -1;for (int i 2; i < num - 1; i) {if …

Java期末题库

根据如下图所示数据库信息&#xff0c;完成1-3小题。 &#xff08;1&#xff09;使用JDBC数据库连接技术&#xff0c;编写JDBCUtil工具类&#xff0c;在该类中定义getCon方法用于获得与数据库的连接对象&#xff0c;定义closeAll方法用于释放连接对象等资源。 import java.sql…

2022史上最全java面试题题库大全800题含答案

2022史上最全java面试题题库大全800题含答案 1、 meta标签的作用是什么 2、 ReenTrantLock可重入锁&#xff08;和synchronized的区别&#xff09;总结 3、 Spring中的自动装配有哪些限制&#xff1f; 4、 什么是可变参数&#xff1f; 5、 什么是领域模型(domain model)&#…

全国计算机等级考试——二级JAVA完整大题题库【五十三道】

全国计算机等级考试二级 JAVA 题目内容 编写于2023.04.10 分为40道选择题和3道大题&#xff08;大题是程序填空类型&#xff09; 其中选择题只能进去做一次&#xff0c;一旦退出来则不可再进&#xff08;注意&#xff01;&#xff09;。大题可以重复进入&#xff0c;重复做。…

java面试题题库大全800题

1、 meta标签的作用是什么 2、 ReenTrantLock可重入锁&#xff08;和synchronized的区别&#xff09;总结 3、 Spring中的自动装配有哪些限制&#xff1f; 4、 什么是可变参数&#xff1f; 5、 什么是领域模型(domain model)&#xff1f;贫血模型(anaemic domain model)和充血模…

Java基础习题库

Java基础习题库 目录 Java基础习题库 一、Java基础之概述 1.JDK,JRE,JVM三者之间的关系&#xff0c;以及JDK、JRE包含的主要结构有哪些 2.为什么要配置path环境变量&#xff1f;如何配置&#xff1f; 3.创建如下的类&#xff0c;使得运行的话可以输出&#xff1a; 4.编译…

Javase MINA框架

MINA是一个基于TCP/IP通信的JAVA框架&#xff0c;MINA可以帮助我们快速开发高性能、高扩展的网络通信应用&#xff0c;提供了事件驱动、异步操作的编程模型&#xff0c;默认使用NIO作为底层支持 客户端实现步骤&#xff1a;

基于Java后台(Springboot框架)+前端小程序(MINA框架)+Mysql数据库的疫苗预约小程序系统设计与实现

项目背景和意义 目的&#xff1a;本课题主要目标是设计并能够实现一个基于微信小程序疫苗预约系统&#xff0c;前台用户使用小程序&#xff0c;后台管理使用基JAVAMySql技术&#xff1b;通过后台添加疫苗内容、价格、开放预约的日期和时间段&#xff0c;用户通过小程序登录&…

Spring Boot Starter之Mina框架封装

封装目的 目前是将Mina与Springboot的自动装配然后结合自身公司的业务对Mina进行统一的封装&#xff0c;目的是让代码可读性提高&#xff0c;也跟加便于使用&#xff0c;不用再写重复的代码 功能介绍 实现功能&#xff1a;可以通过注解的方式自动配置Mina服务端相关的代码 …

java mina 框架 获取字节_浅谈Java的Mina框架传递对象

接触java的Mina框架已经有很多时间了&#xff0c;在网上也读过了很多的相关文章&#xff0c;发现Mina框架的确是一个值得拿来好好研究的东西&#xff0c;前些日子写了一个山寨QQ项目&#xff0c;其中的通信部分用到了java中自带的InputStream&#xff0c;OutputStream&#xff…

Java网络编程之MINA框架(1)

1、MINA&#xff1a; 一个简洁易用的基于TCP/IP通信的JAVA框架 2、下载地址&#xff1a; http://mina.apache.org/downloads-mina_2_0.html 3、至少需要&#xff1a; (在下载的文件中找以下两个jar包导入工程中) mina-core-2.0.21.jar、slf4j-api-1.7.26.jar 4、开发一个Mina应…

浅谈Mina框架

一、简介 Apache Mina Server 是一个网络通信应用框架&#xff0c;也就是说&#xff0c; 也可以提供JAVA对象的序列化服务、虚拟机管道通信服务等&#xff09;&#xff0c;Mina可以帮助我们快速开发高性能、高扩展性的网络通信应用&#xff0c;Mina提供了事件驱动、异步&#…

java mina框架实例_Apache Mina框架实践

1.为什么要用Apache Mina框架 ApacheMina Server 是一个网络通信应用框架,Mina 可以帮助我们快速开发高性能、高扩展性的网络通信应用&#xff0c;Mina 提供了事件驱动、异步(Mina 的异步IO 默认使用的是JAVANIO 作为底层支持)操作的编程模型。 2.ApacheMina框架使用 Mina的执行…

mina框架详解-小白收藏

目录 mina框架详解 1 简介 1.1 工作流程 1.2 服务端流程 2 简单的TCPServer 3 简单的TCPClient 4 介绍Mina的TCP的主要接口 5 日志配置 6 过滤器 7 协议编解码器 8 线程模型配置 mina框架详解 1 简介 Apache Mina Server 是一个网络通信应用框架&#xff0c;也就是…

Mina网络通信框架

认识 Mina Apache Mina Server 是一个网络通信应用框架&#xff0c;与 Netty 出自同一作者&#xff0c;Netty 借鉴了部分 Mina 的设计思路。 Mina 主要是对基于 TCP/IP、UDP/IP 协议栈的通信框架&#xff0c;Mina 可以帮助我们快速开发高性能、高扩展性的网络通信应用&#x…

MINA框架

MINA框架 一、小程序MINA框架分为三个部分&#xff1a; 有 View(视图层)、App Service(逻辑层)和 Natice(系统层)。 1、View(视图层) 视图层包含了小程序多个页面、每个页面都有WXML文件和 WXSS文件&#xff0c;是搭建页面视图的结构和展现样式。 2、App Service(逻辑层) …

图文详解mina框架

Apache Mina Server 是一个网络通信应用框架,也就是说,它主要是对基于TCP/IP、UDP/IP协议栈的通信框架(当然,也可以提供JAVA 对象的序列化服务、虚拟机管道通信服务等),Mina 可以帮助我们快速开发高性能、高扩展性的网络通信应用,Mina 提供了事件驱动、异步(Mina 的异步…

要点初见:用Python进行微观交通模型仿真——基于SUMO的伯克利开源项目Flow Project初探与拓展

后续拓展&#xff1a;要点初见&#xff1a;安装教程与二度拓展——基于SUMO的Flow Project&#xff08;附代码链接&#xff09; 通俗来讲&#xff0c;微观交通模型仿真就是从车辆个体的视角&#xff08;看动画&#xff09;进行交通流仿真&#xff0c;对车辆个体随时间、空间的…