2023最新面试题-Java-6

news2024/11/16 19:29:09

1. Date API

Java 8 在包 java.time 下包含了一组全新的时间日期 API 。新的日期 API 和开源的 Joda-Time 库差不多,但 又不完全一样,下面的例子展示了这组新API 里最重要的一些部分:
Clock 类提供了访问当前日期和时间的方法, Clock 是时区敏感的,可以用来取代
System.currentTimeMillis() 来获取当前的微秒数。某一个特定的时间点也可以使用 Instant 类来表示, Instant类也可以用来创建老的 java.util.Date 对象。
代码如下 :
        Clock clock = Clock.systemDefaultZone();
        long millis = clock.millis();
        Instant instant = clock.instant();
        Date legacyDate = Date.from(instant);
        System.out.println(millis);
        System.out.println(legacyDate);
LocalTime 本地时间
        LocalTime now1 = LocalTime.of(23, 59, 59);
        LocalTime now2 = LocalTime.of(10,10, 59);
        System.out.println(now1.isBefore(now2)); // false
        long hoursBetween = ChronoUnit.HOURS.between(now1, now2);
        long minutesBetween = ChronoUnit.MINUTES.between(now1, now2);
        System.out.println(hoursBetween);
        System.out.println(minutesBetween);
        System.out.println(now1); // 23:59:59
System.out.println(now3);
LocalDate 本地日期
        LocalDate today = LocalDate.now();
        LocalDate tomorrow = today.plus(1, ChronoUnit.DAYS);
        LocalDate yesterday = tomorrow.minusDays(2);
        LocalDate independenceDay = LocalDate.of(2014, Month.JULY, 4);
        DayOfWeek dayOfWeek = independenceDay.getDayOfWeek();

        System.out.println(today);
        System.out.println(tomorrow);
        System.out.println(yesterday);
        System.out.println(independenceDay);
        System.out.println(dayOfWeek);
从字符串解析一个 LocalDate 类型和解析 LocalTime 一样简单:
代码如下
DateTimeFormatter germanFormatter =
 DateTimeFormatter
 .ofLocalizedDate(FormatStyle.MEDIUM)
 .withLocale(Locale.GERMAN);
LocalDate xmas = LocalDate.parse("24.12.2014", germanFormatter);
System.out.println(xmas); // 2014-12-24
LocalDateTime 本地日期时间
LocalDateTime sylvester = LocalDateTime.of(2014, Month.DECEMBER, 31, 23, 59, 59);
DayOfWeek dayOfWeek = sylvester.getDayOfWeek();
System.out.println(dayOfWeek); // WEDNESDAY
Month month = sylvester.getMonth();
System.out.println(month); // DECEMBER
long minuteOfDay = sylvester.getLong(ChronoField.MINUTE_OF_DAY);
System.out.println(minuteOfDay); // 1439
格式化 LocalDateTime 和格式化时间和日期一样的,除了使用预定义好的格式外,我们也可以自己定义 格式:
DateTimeFormatter formatter =
 DateTimeFormatter
 .ofPattern("MMM dd, yyyy - HH:mm");
LocalDateTime parsed = LocalDateTime.parse("Nov 03, 2014 - 07:13", formatter);
String string = formatter.format(parsed);
System.out.println(string); // Nov 03, 2014 - 07:13

2. Annotation 注解

Java 8 中支持多重注解了,先看个例子来理解一下是什么意思。
首先定义一个包装类 Hints 注解用来放置一组具体的 Hint 注解:

代码如下:

@interface Hints {
 Hint[] value();
}
@Repeatable(Hints.class)
@interface Hint {
 String value();
}
Java 8 允许我们把同一个类型的注解使用多次,只需要给该注解标注一下 @Repeatable 即可。
1: 使用包装类当容器来存多个注解(老方法)
代码如下 :
@Hints({@Hint("hint1"), @Hint("hint2")})
class Person {}
2 :使用多重注解(新方法)
代码如下 :
@Hint("hint1")
@Hint("hint2")
class Person {}
第二个例子里 java 编译器会隐性的帮你定义好 @Hints 注解,了解这一点有助于你用反射来获取这些信 息:
Hint hint = Person.class.getAnnotation(Hint.class);
System.out.println(hint); // null
Hints hints1 = Person.class.getAnnotation(Hints.class);
System.out.println(hints1.value().length); // 2
Hint[] hints2 = Person.class.getAnnotationsByType(Hint.class);
System.out.println(hints2.length); // 2

3.  ConcurrentHashMap的红黑树实现分析

红黑树
红黑树是一种特殊的二叉树,主要用它存储有序的数据,提供高效的数据检索,时间复杂度为 O(lgn)
每个节点都有一个标识位表示颜色,红色或黑色,有如下 5 种特性:
1 、每个节点要么红色,要么是黑色;
2 、根节点一定是黑色的;
3 、每个空叶子节点必须是黑色的;
4 、如果一个节点是红色的,那么它的子节点必须是黑色的;
5 、从一个节点到该节点的子孙节点的所有路径包含相同个数的黑色节点;
结构示意图

只要满足以上 5 个特性的二叉树都是红黑树,当有新的节点加入时,有可能会破坏其中一些特性,需要通
过左旋或右旋操作调整树结构,重新着色,使之重新满足所有特性。

ConcurrentHashMap 红黑树实现
谈谈 ConcurrentHashMap1.7 1.8 的不同实现中已经提到,在 1.8 的实现中,当一个链表中的元素达到 8
个时,会调用 treeifyBin() 方法把链表结构转化成红黑树结构,实现如下:
private final void treeifyBin(Node<K,V>[] tab, int index) {
Node<K,V> b; int n, sc;
if (tab != null) {
if ((n = tab.length) < MIN_TREEIFY_CAPACITY)
tryPresize(n << 1);
else if ((b = tabAt(tab, index)) != null && b.hash >= 0) {
synchronized (b) {
if (tabAt(tab, index) == b) {
TreeNode<K,V> hd = null, tl = null;
for (Node<K,V> e = b; e != null; e = e.next) {
TreeNode<K,V> p =
new TreeNode<K,V>(e.hash, e.key, e.val,
null, null);
if ((p.prev = tl) == null)
hd = p;
else
tl.next = p;
tl = p;
}
setTabAt(tab, index, new TreeBin<K,V>(hd));
}
}
}
}
}
从上述实现可以看出:并非一开始就创建红黑树结构,如果当前 Node 数组长度小于阈值
MIN_TREEIFY_CAPACITY ,默认为 64 ,先通过扩大数组容量为原来的两倍以缓解单个链表元素过大的性
能问题。
红黑树构造过程
下面对红黑树的构造过程进行分析:
1 、通过遍历 Node 链表,生成对应的 TreeNode 链表,其中 TreeNode 在实现上继承了 Node 类;
class TreeNode<K,V> extends Node<K,V> {
TreeNode<K,V> parent; // red-black tree links
TreeNode<K,V> left;
TreeNode<K,V> right;
TreeNode<K,V> prev;
// needed to unlink next upon deletion
boolean red;
}
假设 TreeNode 链表如下,其中节点中的数值代表 hash 值:

2 、根据 TreeNode 链表初始化 TreeBin 类对象, TreeBin 在实现上同样继承了 Node 类,所以初始化完
成的 TreeBin 类对象可以保持在 Node 数组中;
class TreeBin<K,V> extends Node<K,V> {
TreeNode<K,V> root;
volatile TreeNode<K,V> first;
volatile Thread waiter;
volatile int lockState;
// values for lockState
// set while holding write lock
static final int WRITER = 1;
// set when waiting for write lock
static final int WAITER = 2;
// increment value for setting read lock
static final int READER = 4;
}
3 、遍历 TreeNode 链表生成红黑树,一开始二叉树的根节点 root 为空,则设置链表中的第一个节点 80
root ,并设置其 red 属性为 false ,因为在红黑树的特性 1 中,明确规定根节点必须是黑色的;
for (TreeNode<K,V> x = b, next; x != null; x = next) {
next = (TreeNode<K,V>)x.next;
x.left = x.right = null;
if (r == null) {
x.parent = null;
x.red = false;
r = x;
}
4 、加入节点 60 ,如果 root 不为空,则通过比较节点 hash 值的大小将新节点插入到指定位置,实现如
下:
K k = x.key;
int h = x.hash;
Class<?> kc = null;
for (TreeNode<K,V> p = r;;) {
int dir, ph;
K pk = p.key;
if ((ph = p.hash) > h)
dir = -1;
else if (ph < h)
dir = 1;
else if ((kc == null &&
(kc = comparableClassFor(k)) == null) ||
(dir = compareComparables(kc, k, pk)) == 0)
dir = tieBreakOrder(k, pk);
TreeNode<K,V> xp = p;
if ((p = (dir <= 0) ? p.left : p.right) == null) {
x.parent = xp;
if (dir <= 0)
xp.left = x;
else
xp.right = x;
r = balanceInsertion(r, x);
break;
}
}
其中 x 代表即将插入到红黑树的节点, p 指向红黑树中当前遍历到的节点,从根节点开始递归遍历, x
的插入过程如下:
1) 、如果 x hash 值小于 p hash 值,则判断 p 的左节点是否为空,如果不为空,则把 p 指向其左节
点,并继续和 p 进行比较,如果 p 的左节点为空,则把 x 指向的节点插入到该位置;
2) 、如果 x hash 值大于 p hash 值,则判断 p 的右节点是否为空,如果不为空,则把 p 指向其右节
点,并继续和 p 进行比较,如果 p 的右节点为空,则把 x 指向的节点插入到该位置;
3) 、如果 x hash 值和 p hash 值相等,怎么办?
解决:首先判断节点中的 key 对象的类是否实现了 Comparable 接口,如果实现 Comparable 接口,则
调用 compareTo 方法比较两者 key 的大小,但是如果 key 对象没有实现 Comparable 接口,或则
compareTo 方法返回了 0 ,则继续调用 tieBreakOrder 方法计算 dir 值, tieBreakOrder 方法实现如
下:
static int tieBreakOrder(Object a, Object b) {
int d;
if (a == null || b == null ||
(d = a.getClass().getName().
compareTo(b.getClass().getName())) == 0)
d = (System.identityHashCode(a) <= System.identityHashCode(b) ?
-1 : 1);
return d;
}
最终比较 key 对象的默认 hashCode() 方法的返回值,因为 System.identityHashCode(a) 调用的是对
a 默认的 hashCode()
插入节点 60 之后的二叉树:

5 、当有新节点加入时,可能会破坏红黑树的特性,需要执行 balanceInsertion() 方法调整二叉树,
使之重新满足特性,方法中的变量 xp 指向 x 的父节点, xpp 指向 xp 父节点, xppl xppr 分别指向
xpp 的左右子节点, balanceInsertion() 方法首先会把新加入的节点设置成红色。
①、加入节点 60 之后,此时 xp 指向节点 80 ,其父节点为空,直接返回
if ((xp = x.parent) == null) {
x.red = false;
return x;
}
else if (!xp.red || (xpp = xp.parent) == null)
return root;
调整之后的二叉树:

 ②、加入节点50,二叉树如下:

 继续执行 balanceInsertion() 方法调整二叉树,此时节点50的父节点60是左儿子,走如下逻辑:

if (xp == (xppl = xpp.left)) {
if ((xppr = xpp.right) != null && xppr.red) {
xppr.red = false;
xp.red = false;
xpp.red = true;
x = xpp;
}else {
if (x == xp.right) {
root = rotateLeft(root, x = xp);
xpp = (xp = x.parent) == null ? null : xp.parent;
}
if (xp != null) {
xp.red = false;
if (xpp != null) {
xpp.red = true;
root = rotateRight(root, xpp);
}
}
}
}
根据上述逻辑,把节点 60 设置成黑色,把节点 80 设置成红色,并对节点 80 执行右旋操作,右旋实现如
下:
static <K,V> TreeNode<K,V> rotateRight(TreeNode<K,V> root,
TreeNode<K,V> p) {
TreeNode<K,V> l, pp, lr;
if (p != null && (l = p.left) != null) {
if ((lr = p.left = l.right) != null)
lr.parent = p;
if ((pp = l.parent = p.parent) == null)
(root = l).red = false;
else if (pp.right == p)
pp.right = l;
else
pp.left = l;
l.right = p;
p.parent = l;
}
return root;
}
右旋之后的红黑树如下:

 ③、加入节点70,二叉树如下:

继续执行 balanceInsertion() 方法调整二叉树,此时父节点 80 是个右儿子,节点 70 是左儿子,且叔节
50 不为空,且是红色的,则执行如下逻辑:
if (xppl != null && xppl.red) {
xppl.red = false;
xp.red = false;
xpp.red = true;
x = xpp;
}
此时二叉树如下:

 此时 x 指向 xpp ,即节点60,继续循环处理 x ,设置其颜色为黑色,最终二叉树如下:

 ④、加入节点20,二叉树变化如下:

因为节点 20 的父节点 50 是一个黑色的节点,不需要进行调整;
⑤、加入节点 65 ,二叉树变化如下:

1 、对节点 20 执行左旋操作;
2 、对节点 50 执行右旋操作;
最后加入节点 10 ,二叉树变化如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/410482.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springboot加载命令行参数ApplicationArguments

往期文章 springcloud整合knike4j聚合微服务接口文档 spring源码 - 条件注解ConditionnalOnClass的原理分析 springboot项目实现导出pdf功能&#xff0c;这也太简单了吧 目录 文章目录往期文章目录一、介绍二、通过应用程序参数获取配置1. 通过bean获取应用程序参数2. 通过V…

在外web浏览器远程访问jupyter notebook服务器

文章目录前言视频教程1. Python环境安装2. Jupyter 安装3. 启动Jupyter Notebook4. 远程访问4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口5. 固定公网地址转载自远控源码文章&#xff1a;公网远程访问jupyter notebook【cpolar内网穿透】 前言 Jupyter Notebook&#…

我现在必须new一个对象!!!

目录 前言 1.new 2.delete 3.底层逻辑 4.定位new 5.对比 前言 &#x1f383;之前在使用C语言的时候&#xff0c;我们便使用 malloc 和 calloc 等函数进行动态内存的开辟。但 C 之中又引入了两个操作符 new 和 delete 来代替C语言中的函数进行动态内存的管理。下面就一起…

苏州源特VPT87DDF01B 隔离变压器 小体积/SMD/3000VDC 隔离

1 产品特点  小体积隔离变压器  隔离电压 3000VDC  工作温度&#xff1a;-40~125℃&#xff08;包含产品温升&#xff09;  存储温度&#xff1a;-55~125℃  SMD 表贴安装  回流焊温度&#xff1a;峰值温度≤250℃&#xff08;10s&#xff09;  回流焊次数&#…

Softing新版HART多路复用器软件支持西门子控制器

用于访问配置和诊断数据的HART多路复用器软件——Softing smartLink SW-HT&#xff0c;现在支持西门子的ET200远程IO和FDT/DTM接口。 smartLink SW-HT是一个基于Docker容器的软件应用。通过该软件&#xff0c;用户可以快速地访问以太网远程IO的HART设备&#xff0c;并且无需额外…

【Linux】进程间通信之管道(pipe)

文章目录前言为什么要进程间通信进程间通信的理论依据管道管道的原理创建匿名管道管道的特点管道的场景利用管道控制子进程命名管道命名管道的打开规则命名管道和匿名管道的区别用命名管道实现server和client通信前言 大家好久不见&#xff0c;今天开始我们将进入进程间通信章…

redis高可用方案:主从复制+哨兵模式,经典案例:一主二从三哨兵,及springboot集成配置

Redis高可用方案&#xff1a;主从复制哨兵模式 经典案例&#xff1a;一主二从三哨兵&#xff0c;及springboot集成配置 第一.配置 1.主节点配置&#xff08;redis.conf&#xff09; # 主节点配置 仅展示必要配置 redis.conf # 保护模式设置为关&#xff0c;方便其他节点访问…

推荐几款炫酷的 MySQL 可视化管理工具!好用到爆!!

MySQL 的管理维护工具非常多&#xff0c;除了系统自带的命令行管理工具之外&#xff0c;还有许多其他的图形化管理工具&#xff0c;工具好用是一方面&#xff0c;个人的使用习惯也很重要&#xff0c;这里介绍 13 款 MySQL 图形化管理工具&#xff0c;供大家参考。 1&#xff1a…

vite .env.test环境使用ant design vue ,打包后a-date-picker控件无法选择日期

前端开发后台管理系统&#xff0c;常用的UI库当属Element UI和 Ant Design Vue&#xff0c;但是前段时间遇到一个奇葩问题&#xff0c;在这里记录一下&#xff0c;防止小伙伴们踩坑。 后台系统&#xff0c;大家肯定都用过时间控件&#xff0c;本期我们使用的是ant design vue&…

2道关于chan的面试题

题目一: 下面关于通道描述正确的是: 1.读nil chan会触发panic 2.写nil chan会触发panic 3.读关闭的chan会触发panic 4.写关闭的chan会触发panic解答&#xff1a;这个提涉及到2个知识点&#xff0c;操作nil的chan会怎么样&#xff0c;操作关闭的chan会怎么样&#xff0c;下面我…

双目相机测距原理

双目相机测距是一种常用的计算机视觉技术&#xff0c;它利用两个摄像头同时拍摄同一场景&#xff0c;通过测量两个摄像头视野中同一物体在图像上的像素差异&#xff0c;从而计算出物体距离的方法。 具体原理如下&#xff1a; 双目相机的构成 双目相机由两个摄像头组成&#…

用ChatGPT怎么赚钱?普通人用这5个方法也能赚到生活费

ChatGPT在互联网火得一塌糊涂&#xff0c;因为它可以帮很多人解决问题。比如&#xff1a;帮编辑人员写文章&#xff0c;还可以替代程序员写代码&#xff0c;帮策划人员写文案策划等等。ChatGPT这么厉害&#xff0c;能否用它来赚钱呢&#xff1f;今天和大家分享用ChatGPT赚钱的5…

Cesium关于3Dtiles的细节分享

介绍 介绍一下Cesium中有关3dTiles的奇淫技巧&#xff0c;存在一些埋坑的地方&#xff0c;以下内容仅为自己摸索的细节和方法&#xff0c;仅供参考&#xff0c;若有更好的办法欢迎讨论 通用快速获取feature中包含的属性信息 有时候需要快速获得3dTiles中的feature中的属性信…

deb文件如何安装到iphone方法分享

Cydia或同类APT管理软件在线安装 Cydia或同类APT管理软件在线安装,这个是最佳的安装方式,因为通常无需考虑依赖关系,但缺点是对网络的要求比较高;命令行中以dpkg-iXXX.deb的形式安装,好处是可以以通配符一次性安装多个deb,而且也可以直接看到脚本的运行状况和安装成功/失…

执行命令行程序测试自动化

这几天有一个小工具需要做测试&#xff0c;是一个命令行工具&#xff0c;这个命令行工具有点类似mdbg等命令行工具&#xff0c;即程序运行后&#xff0c;在命令行等待用户敲入的命令&#xff0c;处理命令并显示结果&#xff0c;再继续等待用户敲入新的命令。 原来的测试用例都…

Vue实现自动化平台(五)--用例编辑页面

上一章&#xff1a;Vue实现自动化平台&#xff08;四&#xff09;--接口管理页面的实现_做测试的喵酱的博客-CSDN博客 github地址&#xff1a;https://github.com/18713341733/vuemiaotest 这个目前只是用来练手的&#xff0c;项目还没成型。等以后我写完了&#xff0c;再更…

公网远程访问局域网SQL Server数据库【无公网IP内网穿透】

目录 1.前言 2.本地安装和设置SQL Server 2.1 SQL Server下载 2.2 SQL Server本地连接测试 2.3 Cpolar内网穿透的下载和安装 2.3 Cpolar内网穿透的注册 3.本地网页发布 3.1 Cpolar云端设置 3.2 Cpolar本地设置 4.公网访问测试 5.结语 转发自CSDN远程穿透的文章&…

不用但一定要懂 ---- iOS 之 响应链、传递链 与 手势识别

iOS 事件的主要由&#xff1a;响应连 和 传递链 构成。一般事件先通过传递链&#xff0c;传递下去。响应链&#xff0c;如果上层不能响应&#xff0c;那么一层一层通过响应链找到能响应的UIResponse。 响应链&#xff1a;由最基础的view向系统传递&#xff0c;first view ->…

c/c++:原码,反码,补码和常见的数据类型取值范围,溢出

c/c&#xff1a;原码&#xff0c;反码&#xff0c;补码和常见的数据类型取值范围&#xff0c;溢出 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&#xff0c;此时学会c的话&#xff0c; 我所知道的周边的会c的同学&#xff0c;可手握…

前脚我的 GPT4 被封,后脚收到了文心一言的邀请账号

大家好&#xff0c;我是二哥呀。 一早醒来&#xff0c;我的 ChatGPT Plus 账号就惨遭封禁&#xff0c;很不幸&#xff0c;我刚冲的 Plus 会员&#xff0c;用了不到一周的时间&#xff08;&#x1f62d;&#xff09;。 我没用亚洲的IP&#xff0c;所以网上传的那些不使用亚洲IP…