前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >2021-Java后端工程师面试指南-(Java基础篇)

2021-Java后端工程师面试指南-(Java基础篇)

作者头像
用户9927510
发布2022-07-29 08:56:15
3620
发布2022-07-29 08:56:15
举报
文章被收录于专栏:六脉神剑的程序人生

前言

文本已收录至我的GitHub仓库,欢迎Star:https://github.com/bin392328206/six-finger 种一棵树最好的时间是十年前,其次是现在

Tips

面试指南系列,很多情况下不会去深挖细节,是小六六以被面试者的角色去回顾知识的一种方式,所以我默认大部分的东西,作为面试官的你,肯定是懂的。

https://www.processon.com/view/link/600ed9e9637689349038b0e4

上面的是脑图地址

叨絮

可能大家觉得有点老生常谈了,确实也是。面试题,面试宝典,随便一搜,根本看不完,也看不过来,那我写这个的意义又何在呢?其实嘛我写这个的有以下的目的

  • 第一就是通过一个体系的复习,让自己前面的写的文章再重新的过一遍,总结升华嘛
  • 第二就是通过写文章帮助大家建立一个复习体系,我会将大部分会问的的知识点以点带面的形式给大家做一个导论

然后下面是前面的文章汇总

最后就是以面试题的形式来回顾所有的知识点,会整理一些比较常见的面试题和自己实际开发碰到的问题等题目。

Java基本功

Java字符型常量和字符串常量的区别?

我们在开发的过程中,用的比较多的应该是字符串,所以要熟悉下字符常量,我们可以回答

  • 形式上: 字符常量是单引号引起的一个字符; 字符串常量是双引号引起的 0 个或若干个字符
  • 含义上: 字符常量相当于一个整型值( ASCII 值),可以参加表达式运算; 字符串常量代表一个地址值(该字符串在内存中存放位置)
  • 占内存大小 字符常量只占 2 个字节; 字符串常量占若干个字节

String和StringBuilder、StringBuffer的区别?

  • Java 平台提供了两种类型的字符串:String 和 StringBuffer/StringBuilder,它们可以储存和操作字符串。
  • 其中 String 是只读字符串,也就意味着 String 引用的字符串内容是不能被改变的。
  • 而 StringBuffer/StringBuilder 类表示的字符串对象可以直接进行修改。StringBuilder 是 Java 5 中引入的,它和 StringBuffer 的方法完全相同,区别在于它是在单线程环境下使用的,因为它的所有方面都没有被 synchronized 修饰,因此它的效率也比 StringBuffer 要高。

小六六多嘴下,其实也是在告诫自己,其实我相信这个题目的答案大部分的人都是会的,也背的滚瓜烂熟,但是我们真正在开发的过程中确是没有遵守的,比如有时候我们处理一些逻辑的时候,需要拼接些字段的时候我们会习惯的用+,不知道有没有同款开发。哈哈,小六六和大家一起尽量养成好的开发习惯哈

说说反射的用途及实现

Java 反射机制是一个非常强大的功能,在很多的项目比如 Spring,MyBatis 都都可以看到反射的身影。通过反射机制,我们可以在运行期间获取对象的类型信息。利用这一点我们可以实现工厂模式和代理模式等设计模式,同时也可以解决 Java 泛型擦除等令人苦恼的问题。

获取一个对象对应的反射类,在 Java 中有下列方法可以获取一个对象的反射类

  • new 一个对象,然后对象.getClass()方法
  • 通过 Class.forName() 方法
  • 使用 类.class

说说有没有碰到BigDecimal的坑,或者说需要注意的点

  • 我们在使用BigDecimal时,为了防止精度丢失,推荐使用它的 BigDecimal(String) 构造方法来创建对象。其实就是想知道我们的实际开发是否有注意到这些点,

说说你平时是怎么把一个逗号隔开的字符串变成一个集合的,类似于("1,2,3")这种

  • List myList = Arrays.stream(myArray).collect(Collectors.toList()),建议使用这种方式,而不是List myList = Arrays.asList(1, 2, 3);
  • 至于原因就是Arrays.asList()将数组转换为集合后,底层其实还是数组

说说String s="abc"和String s=new String("abc")区别;

  • 相信大家对这道题并不陌生,答案也是众所周知的,1个或2个。
  • 首先在堆中(不是常量池)创建一个指定的对象"abc",并让str引用指向该对象
  • 在字符串常量池中查看,是否存在内容为"abc"字符串对象
  • 若存在,则将new出来的字符串对象与字符串常量池中的对象联系起来
  • 若不存在,则在字符串常量池中创建一个内容为"abc"的字符串对象,并将堆中的对象与之联系起来

聊聊Java中的SPI

系统设计的各个抽象,往往有很多不同的实现方案,在面向的对象的设计里,一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里涉及具体的实现类,就违反了可拔插的原则,如果需要替换一种实现,就需要修改代码。为了实现在模块装配的时候能不在程序里动态指明,这就需要一种服务发现机制。Java SPI就是提供这样的一个机制:为某个接口寻找服务实现的机制。有点类似IOC的思想,就是将装配的控制权移到程序之外,在模块化设计中这个机制尤其重要。所以SPI的核心思想就是解耦。

聊聊Java 8有哪些特性

  • 函数式接口
  • 接口可以有实现方法,而且不需要实现类去实现其方法。
  • lambda表达式
  • stream流
  • 日期时间 API LocalDateTime年月日十分秒;LocalDate日期;LocalTime时间
  • Optional 类 虽然说目前最新的版本已经是15了,但是大部分企业还是用的8,所以就聊聊这个拉。

说说成员变量与局部变量的区别有哪些?

  • 成员变量可以被 public,private,static 等修饰符所修饰,而局部变量不能被访问控制修饰符及 static 所修饰;但是,成员变量和局部变量都能被 final 所修饰。
  • 从变量在内存中的存储方式来看:如果成员变量是使用static修饰的,那么这个成员变量是属于类的,如果没有使用static修饰,这个成员变量是属于实例的。而对象存在于堆内存,局部变量则存在于栈内存
  • 从变量在内存中的生存时间上看:成员变量是对象的一部分,它随着对象的创建而存在,而局部变量随着方法的调用而自动消失。
  • 成员变量如果没有被赋初值:则会自动以类型的默认值而赋值(一种情况例外:被 final 修饰的成员变量也必须显式地赋值),而局部变量则不会自动赋值。

说说构造方法有哪些特性?

  • 名字与类名相同。
  • 没有返回值,但不能用 void 声明构造函数。
  • 生成类的对象时自动执行,无需调用。

说说==和equals

  • == : 它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象(基本数据类型==比较的是值,引用数据类型==比较的是内存地址)。
  • equals() : 它的作用也是判断两个对象是否相等。但它一般有两种使用情况:
    • 情况 1:类没有覆盖 equals() 方法。则通过 equals() 比较该类的两个对象时,等价于通过“==”比较这两个对象。
    • 情况 2:类覆盖了 equals() 方法。一般,我们都覆盖 equals() 方法来比较两个对象的内容是否相等;若它们的内容相等,则返回 true (即,认为这两个对象相等)。

聊聊Java的四种引用,强弱软虚

小六六这边说下,其实我们作为一个crud仔,平时真正接触到的也许就是强引用了,但是也不是说其他的引用方式没有用,存在即合理,我们来看看他们具体的作用吧!感觉应该放到JVM模块的,算了,就这个吧

  • 强引用:最普遍的一种引用方式,如String s = "abc",变量s就是字符串“abc”的强引用,只要强引用存在,则垃圾回收器就不会回收这个对象。
  • 软引用:用于描述还有用但非必须的对象,如果内存足够,不回收,如果内存不足,则回收。一般用于实现内存敏感的高速缓存(自定义内存cached的时候用),软引用可以和引用队列ReferenceQueue联合使用,如果软引用的对象被垃圾回收,JVM就会把这个软引用加入到与之关联的引用队列中。
  • 弱引用:弱引用和软引用大致相同,弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。(这个就比较垃圾了)
  • 虚引用:虚引用不会改变对象的生命周期,如果一个对象仅持有虚引用,那么它就和没有任何引用一样。(其实小六六自己对于虚引用的理解还是因为ThreadLocal,防止我们忘记remove)

Java容器集合

聊聊数组的特点呗

  • 一致性:数组只能保存相同数据类型元素,元素的数据类型可以是任何相同的数据类型。
  • 有序性:数组中的元素是有序的,通过下标访问。
  • 不可变性:数组一旦初始化,则长度(数组中元素的个数)不可变。数组是一种连续存储线性结构,元素类型相同,大小相等

说说Java常见的集合有哪些

嗯,我觉得这题会经常问,算是一个对集合考查的引入吧

  • Map接口和Collection接口是所有集合框架的父接口
  • Collection接口的子接口包括:Set接口和List接口
  • Map接口的实现类主要有:HashMap、TreeMap、Hashtable、ConcurrentHashMap以及Properties等
  • Set接口的实现类主要有:HashSet、TreeSet、LinkedHashSet等
  • List接口的实现类主要有:ArrayList、LinkedList、Stack以及Vector等

简单聊聊 Set、List、Map的区别

List

  • 可以允许重复的对象。
  • 可以插入多个null元素。
  • 是一个有序容器,保持了每个元素的插入顺序,输出的顺序就是插入的顺序。

Set

  • 不允许重复对象
  • 无序容器,你无法保证每个元素的存储顺序,TreeSet通过 Comparator 或者 Comparable 维护了一个排序顺序。
  • 只允许一个 null 元素

Map

  • Map不是collection的子接口或者实现类。Map是一个接口。
  • Map 的 每个 Entry 都持有两个对象,也就是一个键一个值,Map 可能会持有相同的值对象但键对象必须是唯一的。
  • Map 里你可以拥有随意个 null 值但最多只能有一个 null 键。

他们的使用场景

  • 如果你经常会使用索引来对容器中的元素进行访问,那么 List 是你的正确的选择。如果你已经知道索引了的话,那么 List 的实现类比如 ArrayList 可以提供更快速的访问,如果经常添加删除元素的,那么肯定要选择LinkedList。
  • 如果你想容器中的元素能够按照它们插入的次序进行有序存储,那么还是 List,因为 List 是一个有序容器,它按照插入顺序进行存储。
  • 如果你想保证插入元素的唯一性,也就是你不想有重复值的出现,那么可以选择一个 Set 的实现类,比如 HashSet、LinkedHashSet 或者 TreeSet。所有 Set 的实现类都遵循了统一约束比如唯一性,而且还提供了额外的特性比如 TreeSet 还是一个 SortedSet,所有存储于 TreeSet 中的元素可以使用 Java 里的 Comparator 或者 Comparable 进行排序。LinkedHashSet 也按照元素的插入顺序对它们进行存储。
  • 如果你以键和值的形式进行数据存储那么 Map 是你正确的选择。你可以根据你的后续需要从 Hashtable、HashMap、TreeMap 中进行选择。 `

来聊聊 ArrayList和LinkedList区别

  • ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
  • 对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
  • 对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。

说说Vector和ArrayList 区别:

  • Vector的方法都是同步的(Synchronized),是线程安全的(thread-safe),而ArrayList的方法不是,由于线程的同步必然要影响性能,因此,ArrayList的性能比Vector好。
  • 当Vector或ArrayList中的元素超过它的初始大小时,Vector会将它的容量翻倍,而ArrayList只增加50%的大小,这样,ArrayList就有利于节约内存空间。
  • 我们也可以用Collections.synchronizedList 来生成一个线程安全的List

说说HashSet和TreeSet的区别:

  • TreeSet 是二叉树实现的,Treeset中的数据是自动排好序的,不允许放入null值。
  • HashSet 是哈希表实现的,HashSet中的数据是无序的,可以放入null,但只能放入一个null,两者中的值都不能重复,就如数据库中唯一约束。
  • HashSet要求放入的对象必须实现HashCode()方法,放入的对象,是以hashcode码作为标识的,而具有相同内容的 String对象,hashcode是一样,所以放入的内容不能重复。但是同一个类的对象可以放入不同的实例 。

说说HashMap和HashTable的区别:

  • HashMap是非线程安全的,Hashtable是线程安全的,所以Hashtable重量级一些,因为使用了synchronized关键字来保证线程安全。
  • HashMap允许key和value都为null,而Hashtable都不能为null。
  • HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常

上面的是我们集合的基础,下面来看看一些进阶面试题

能不能深度的总结下ArrayList

  • 默认的无参构造的数组大小为10
  • ArrayList用for循环遍历比iterator迭代器遍历快
  • 一起来总结下它的扩容过程,第一步判断是否需要扩容(就是通过计算当前我数组的长度加上我要添加到数组的长度的和minCapacity 去和当前容量去比较,如果需要的话,那就进行第一次扩容,第一次扩容是的容量大小是原来的1.5倍,扩容之后再把扩容之后的值和前面的那个minCapacity和比较 如果还小的话,就进行第二次扩容,把容量扩成minCapacity,如果minCapacity大于最大容量,则就扩容为最大容量21亿左右

为什么ArrayList的elementData是用transient修饰的

  • ArrayList实现了Serializable接口,这意味着ArrayList是可以被序列化的,用transient修饰elementData意味着我不希望elementData数组被序列化
  • 序列化ArrayList的时候,ArrayList里面的elementData未必是满的,比方说elementData有10的大小,但是我只用了其中的3个,那么是否有必要序列化整个elementData呢?显然没有这个必要,因此ArrayList中重写了writeObject方法。

你重写过 hashcode 和 equals 么,为什么重写 equals 时必须重写 hashCode 方法?

  • 如果两个对象相等,则 hashcode 一定也是相同的
  • 两个对象相等,对两个对象分别调用 equals 方法都返回 true
  • 两个对象有相同的 hashcode 值,它们也不一定是相等的
  • 因此,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖
  • hashCode() 的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class 的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)

聊聊HashSet 如何检查重复

当你把对象加入HashSet时,HashSet 会先计算对象的hashcode值来判断对象加入的位置,同时也会与其他加入的对象的 hashcode 值作比较,如果没有相符的 hashcode,HashSet 会假设对象没有重复出现。但是如果发现有相同 hashcode 值的对象,这时会调用equals()方法来检查 hashcode 相等的对象是否真的相同。如果两者相同,HashSet 就不会让加入操作成功。

说说HashMap 的底层实现

JDK1.8 之前 JDK1.8 之前 HashMap 底层是 数组和链表 结合在一起使用也就是 链表散列。HashMap 通过 key 的 hashCode 经过扰动函数处理过后得到 hash 值,然后通过 (n - 1) & hash 判断当前元素存放的位置(这里的 n 指的是数组的长度),如果当前位置存在元素的话,就判断该元素与要存入的元素的 hash 值以及 key 是否相同,如果相同的话,直接覆盖,不相同就通过拉链法解决冲突。

所谓扰动函数指的就是 HashMap 的 hash 方法。使用 hash 方法也就是扰动函数是为了防止一些实现比较差的 hashCode() 方法 换句话说使用扰动函数之后可以减少碰撞。

JDK1.8之后 相比于之前的版本, JDK1.8 之后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8)(将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树)时,将链表转化为红黑树,以减少搜索时间。

那么你可以聊聊红黑树吗

首先我们知道红黑数是一个二叉查找树, 它有以下的特点

  • 左子树上所有结点的值均小于或等于它的根结点的值。
  • 右子树上所有结点的值均大于或等于它的根结点的值。
  • 左、右子树也分别为二叉排序树。但是一般的二叉树在极端情况下,可能变成线性查找了,那么就失去它的查找特性意义了,而红黑树是一个自平衡树,它最重要的是增加了下面3个规则来确保它的自平衡
  • 每个叶子节点都是黑色的空节点(NIL节点)。
  • 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
  • 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。

这里小六六说下,红黑树还是很复杂的,所以一般往下不会问了,如果变态点,就还会问问自平衡的过程,这边我就不一一解释了,大家自行去找。它的变色,它的左旋,右旋,哈哈确实掉头发。。

HashMap 的长度为什么是 2 的幂次方

  • 首先考虑奇数行不行,在计算hash的时候,确定落在数组的位置的时候,计算方法是(n - 1) & hash ,奇数n-1为偶数,偶数2进制的结尾都是0,经过&运算末尾都是0,会增加hash冲突,并且有一半的空间不会有数据
  • 为啥要是2的幂,不能是2的倍数么,比如6,10?
    • hashmap 结构是数组,每个数组里面的结构是node(链表或红黑树),正常情况下,如果你想放数据到不同的位置,肯定会想到取余数确定放在那个数据里, 计算公式:hash % n,这个是十进制计算。在计算机中, (n - 1) & hash,当n为2次幂时,会满足一个公式:(n - 1) & hash = hash % n,计算更加高效。
    • 只有是2的幂数的数字经过n-1之后,二进制肯定是 ...11111111 这样的格式,这种格式计算的位置的时候(&),完全是由产生的hash值类决定,而不受n-1(组数长度的二进制) 影响。你可能会想, 受影响不是更好么,又计算了一下,类似于扰动函数,hash冲突可能更低了,这里要考虑到扩容了,2的幂次方*2,在二进制中比如4和8,代表2的2次方和3次方,他们的2进制结构相 似,比如 4和8 00000100 0000 1000 只是高位向前移了一位,这样扩容的时候,只需要判断高位hash,移动到之前位置的倍数就可以了,免去了重新计算位置的运算。

HashMap 的扩容伐值为什么是0.75

  • 当负载因子是1.0的时候,也就意味着,只有当数组的8个值(这个图表示了8个)全部填充了,才会发生扩容。这就带来了很大的问题,因为Hash冲突时避免不了的。当负载因子是1.0的时候,意味着会出现大量的Hash的冲突,底层的红黑树变得异常复杂。对于查询效率极其不利。这种情况就是牺牲了时间来保证空间的利用率。
  • 负载因子是0.5的时候,这也就意味着,当数组中的元素达到了一半就开始扩容,既然填充的元素少了,Hash冲突也会减少,那么底层的链表长度或者是红黑树的高度就会降低。查询效率就会增加。
  • 基本上为什么是0.75的答案也就出来了,这是时间和空间的权衡。

HashMap树化的条件

这个小六六说下,如果没看过源码,肯定印象没有那么深刻

  • 第一个肯定是发生了hash碰撞
  • 并且链表的长度大于8就会树化,小于6之后会退化
  • 还有一个条件就是整个hashmap的容量要大于64

JDK1.7版本的hashmap死循环问题知道吗

小六六也大致说下,就是1.7在多线程的情况下,扩容的时候,假设2个线程同时扩容导致的我们链表的相互引用,导致的死循环,也就是我们所说的链表尾插,其实这也不算bug,因为官方明确说了 hashmap不应该在多线程的环境下使用,具体大家自行百度

说说hashmap的put操作

  • 第一步当然是先计算key的hash值(有过处理的 (h = key.hashCode()) ^ (h >>> 16))
  • 第二步调用putval方法,然后判断是否容器中全部为空,如果是的话,就把容器的容量扩容。
  • 第三步,把最大容量和hash值求&值(i = (n - 1) & hash),判断这个数组下标是否有数据,如果没有就把它放进去。还要判断key的equals方法,看是否需要覆盖。
  • 第四步,如果有,说明发生了碰撞,那么继续遍历判断链表的长度是否大于8,如果大于8,就继续把当前链表变成红黑树结构。
  • 第五步,如果没有到8,那么就直接把数据存在链表的尾部
  • 第六步,最后将容器的容量+1。

说说hashmap的resize的操作

  • 如果到达最大容量,那么返回当前的桶,并不再进行扩容操作,否则的话扩容为原来的两倍,返回扩容后的桶;
  • 根据扩容后的桶,修改其他的成员变量的属性值;
  • 根据新的容量创建新的扩建后的桶,并更新桶的引用;
  • 如果原来的桶里面有元素就需要进行元素的转移;
  • 在进行元素转移的时候需要考虑到元素碰撞和转红黑树操作;
  • 在扩容的过程中,按次从原来的桶中取出链表头节点,并对该链表上的所有元素重新计算hash值进行分配;
  • 在发生碰撞的时候,将新加入的元素添加到末尾;
  • 在元素复制的时候需要同时对低位和高位进行操作。

聊聊ConcurrentHashMap 1.7和1.8的比较

ConcurrentHashMap是conccurrent家族中的一个类,由于它可以高效地支持并发操作,以及被广泛使用,经典的开源框架Spring的底层数据结构就是使用ConcurrentHashMap实现的。与同是线程安全的老大哥HashTable相比,它已经更胜一筹,因此它的锁更加细化,而不是像HashTable一样为几乎每个方法都添加了synchronized锁,这样的锁无疑会影响到性能。

1.7和1.8实现线程安全的思想也已经完全变了其中抛弃了原有的Segment 分段锁,而采用了 CAS + synchronized 来保证并发安全性。它沿用了与它同时期的HashMap版本的思想,底层依然由“数组”+链表+红黑树的方式思想。

  • 不采用segment而采用node,锁住node来实现减小锁粒度。
  • 设计了MOVED状态 当resize的中过程中 线程2还在put数据,线程2会帮助resize。
  • 使用3个CAS操作来确保node的一些操作的原子性,这种方式代替了锁。
  • sizeCtl的不同值来代表不同含义,起到了控制的作用。

聊聊ConcurrentHashMap的sizeCtl

  • 负数代表正在进行初始化或扩容操作
  • -1代表正在初始化
  • -N 表示有N-1个线程正在进行扩容操作
  • 正数或0代表hash表还没有被初始化,这个数值表示初始化或下一次进行扩容的大小,这一点类似于扩容阈值的概念。还后面可以看到,它的值始终是当前ConcurrentHashMap容量的0.75倍,这与loadfactor是对应的。

说说ConcurrentHashMap的put方法

  • 第一步,一进去肯定判断key value是否为null 如果为null 抛出异常
  • 第二步,当添加一对键值对的时候,首先会去判断保存这些键值对的数组是不是初始化了,如果没有就初始化数组。
  • 第三步, 通过计算hash值来确定放在数组的哪个位置如果这个位置为空则直接添加(CAS的加锁方式),如果不为空的话,则取出这个节点来
  • 第四步,如果取出来的节点的hash值是MOVED(-1)的话,则表示当前正在对这个数组进行扩容,复制到新的数组,则当前线程也去帮助复制
  • 第五步,如果这个节点,不为空,也不在扩容,则通过synchronized来加锁,进行添加操作
  • 第六步,如果是链表的话,则遍历整个链表,直到取出来的节点的key来个要放的key进行比较,如果key相等,并且key的hash值也相等的话,则说明是同一个key,则覆盖掉value,否则的话则添加到链表的末尾
  • 第七步,如果是树的话,则调用putTreeVal方法把这个元素添加到树中去
  • 第八步,最后在添加完成之后,会判断在该节点处共有多少个节点(注意是添加前的个数),如果达到8个以上了的话,则调用treeifyBin方法来尝试将处的链表转为树,或者扩容数

结尾

这个就是一些基础的面试题,当然还是很多不一定那么全,但是如果把这些都能回答出来,其实Java基础这块也算是蛮扎实了。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-02-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 六脉神剑的程序人生 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
    • Tips
      • 叨絮
        • Java基本功
          • Java字符型常量和字符串常量的区别?
          • String和StringBuilder、StringBuffer的区别?
          • 说说反射的用途及实现
          • 说说有没有碰到BigDecimal的坑,或者说需要注意的点
          • 说说你平时是怎么把一个逗号隔开的字符串变成一个集合的,类似于("1,2,3")这种
          • 说说String s="abc"和String s=new String("abc")区别;
          • 聊聊Java中的SPI
          • 聊聊Java 8有哪些特性
          • 说说成员变量与局部变量的区别有哪些?
          • 说说构造方法有哪些特性?
          • 说说==和equals
          • 聊聊Java的四种引用,强弱软虚
        • Java容器集合
          • 聊聊数组的特点呗
          • 说说Java常见的集合有哪些
          • 简单聊聊 Set、List、Map的区别
          • 来聊聊 ArrayList和LinkedList区别
          • 说说Vector和ArrayList 区别:
          • 说说HashSet和TreeSet的区别:
          • 说说HashMap和HashTable的区别:
          • 能不能深度的总结下ArrayList
          • 为什么ArrayList的elementData是用transient修饰的
          • 你重写过 hashcode 和 equals 么,为什么重写 equals 时必须重写 hashCode 方法?
          • 聊聊HashSet 如何检查重复
          • 说说HashMap 的底层实现
          • 那么你可以聊聊红黑树吗
          • HashMap 的长度为什么是 2 的幂次方
          • HashMap 的扩容伐值为什么是0.75
          • HashMap树化的条件
          • JDK1.7版本的hashmap死循环问题知道吗
          • 说说hashmap的put操作
          • 说说hashmap的resize的操作
          • 聊聊ConcurrentHashMap 1.7和1.8的比较
          • 聊聊ConcurrentHashMap的sizeCtl
          • 说说ConcurrentHashMap的put方法
        • 结尾
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档