| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 数据结构与算法 -> 各大厂在三月问得最多的50道Java基础面试题 -> 正文阅读 |
|
[数据结构与算法]各大厂在三月问得最多的50道Java基础面试题 |
1. Arraylist与LinkedList区别可以从它们的底层数据结构、效率、开销进行阐述哈
2. Collections.sort和Arrays.sort的实现原理Collection.sort是对list进行排序,Arrays.sort是对数组进行排序。 Collections.sort底层实现Collections.sort方法调用了list.sort方法 list.sort方法调用了Arrays.sort的方法 因此,Collections.sort方法底层就是调用的Array.sort方法 Arrays.sort底层实现Arrays的sort方法,如下: 如果比较器为null,进入sort(a)方法。如下: 因此,Arrays的sort方法底层就是:
Timesort排序Timsort排序是结合了合并排序(merge.sort)和插入排序(insertion sort)而得出的排序方法; 1.当数组长度小于某个值,采用的是二分插入排序算法,如下:
3. HashMap原理,java8做了什么改变
4. List 和 Set,Map 的区别
5. poll()方法和 remove()方法的区别?Queue队列中,poll() 和 remove() 都是从队列中取出一个元素,在队列元素为空的情况下,remove() 方法会抛出异常,poll() 方法只会返回 null 。 看一下源码的解释吧: /** * Retrieves and removes the head of this queue. This method differs * from {@link #poll poll} only in that it throws an exception if this * queue is empty. * * @return the head of this queue * @throws NoSuchElementException if this queue is empty */ E remove(); /** * Retrieves and removes the head of this queue, * or returns {@code null} if this queue is empty. * * @return the head of this queue, or {@code null} if this queue is empty */ E poll();6. HashMap,HashTable,ConcurrentHash的共同点和区别HashMap
HashTable
ConcurrentHashMap
7. 写一段代码在遍历 ArrayList 时移除一个元素因为foreach删除会导致快速失败问题,fori顺序遍历会导致重复元素没删除,所以正确解法如下: 第一种遍历,倒叙遍历删除 for(int i=list.size()-1; i>-1; i--){ if(list.get(i).equals("jay")){ list.remove(list.get(i)); }}第二种,迭代器删除 Iterator itr = list.iterator();while(itr.hasNext()) { if(itr.next().equals("jay") { itr.remove(); }}8. Java中怎么打印数组?数组是不能直接打印的哈,如下: public class Test { public static void main(String[] args) { String[] jayArray = {"jay", "boy"}; System.out.println(jayArray); }}//output[Ljava.lang.String;@1540e19d打印数组可以用流的方式Strem.of().foreach(),如下: public class Test { public static void main(String[] args) { String[] jayArray = {"jay", "boy"}; Stream.of(jayArray).forEach(System.out::println); }}//outputjayboy打印数组,最优雅的方式可以用这个APi,Arrays.toString() public class Test { public static void main(String[] args) { String[] jayArray = {"jay", "boy"}; System.out.println(Arrays.toString(jayArray)); }}//output[jay, boy]9. TreeMap底层?
10. HashMap 的扩容过程Hashmap的扩容:
11. HashSet是如何保证不重复的可以看一下HashSet的add方法,元素E作为HashMap的key,我们都知道HashMap的可以是不允许重复的,哈哈。 public boolean add(E e) { return map.put(e, PRESENT)==null;}12. HashMap 是线程安全的吗,为什么不是线程安全的?死循环问题?不是线性安全的。 并发的情况下,扩容可能导致死循环问题。 13. LinkedHashMap的应用,底层,原理
14. 哪些集合类是线程安全的?哪些不安全?线性安全的
线性不安全的
15. ArrayList 和 Vector 的区别是什么?
16. Collection与Collections的区别是什么?
17. 如何决定使用 HashMap 还是TreeMap?这个点,主要考察HashMap和TreeMap的区别。 TreeMap实现SortMap接口,能够把它保存的记录根据键排序,默认是按key的升序排序,也可以指定排序的比较器。当用Iterator遍历TreeMap时,得到的记录是排过序的。 18. 如何实现数组和 List之间的转换?List 转 ArrayList 转Array,必须使用集合的 toArray(T[] array),如下: List<String> list = new ArrayList<String>();list.add("jay");list.add("tianluo");// 使用泛型,无需显式类型转换String[] array = list.toArray(new String[list.size()]);System.out.println(array[0]);如果直接使用 toArray 无参方法,返回值只能是 Object[] 类,强转其他类型可能有问题,demo如下: List<String> list = new ArrayList<String>();list.add("jay");list.add("tianluo");String[] array = (String[]) list.toArray();System.out.println(array[0]);运行结果: Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String; at Test.main(Test.java:14)Array 转List使用Arrays.asList() 把数组转换成集合时,不能使用修改集合相关的方法啦,如下: String[] str = new String[] { "jay", "tianluo" };List list = Arrays.asList(str);list.add("boy");运行结果如下: Exception in thread "main" java.lang.UnsupportedOperationException at java.util.AbstractList.add(AbstractList.java:148) at java.util.AbstractList.add(AbstractList.java:108) at Test.main(Test.java:13)因为 Arrays.asList不是返回java.util.ArrayList,而是一个内部类ArrayList。 可以这样使用弥补这个缺点: //方式一:ArrayList< String> arrayList = new ArrayList<String>(strArray.length);Collections.addAll(arrayList, strArray);//方式二:ArrayList<String> list = new ArrayList<String>(Arrays.asList(strArray)) ;19. 迭代器 Iterator 是什么?怎么用,有什么特点?public interface Collection<E> extends Iterable<E> {Iterator<E> iterator();方法如下: next() 方法获得集合中的下一个元素hasNext() 检查集合中是否还有元素remove() 方法将迭代器新返回的元素删除forEachRemaining(Consumer<? super E> action) 方法,遍历所有元素Iterator 主要是用来遍历集合用的,它的特点是更加安全,因为它可以确保,在当前遍历的集合元素被更改的时候,就会抛出 ConcurrentModificationException 异常。 使用demo如下: List<String> list = new ArrayList<>();Iterator<String> it = list. iterator();while(it. hasNext()){ String obj = it. next(); System. out. println(obj);}20. Iterator 和 ListIterator 有什么区别?
21. 怎么确保一个集合不能被修改?很多朋友很可能想到用final关键字进行修饰,final修饰的这个成员变量,如果是基本数据类型,表示这个变量的值是不可改变的,如果是引用类型,则表示这个引用的地址值是不能改变的,但是这个引用所指向的对象里面的内容还是可以改变滴~验证一下,如下: public class Test { //final 修饰 private static final Map<Integer, String> map = new HashMap<Integer, String>(); { map.put(1, "jay"); map.put(2, "tianluo"); } public static void main(String[] args) { map.put(1, "boy"); System.out.println(map.get(1)); }}运行结果如下: //可以洗发现,final修饰,集合还是会被修改呢boy嘻嘻,那么,到底怎么确保一个集合不能被修改呢,看以下这三哥们~
再看一下demo吧 public class Test { private static Map<Integer, String> map = new HashMap<Integer, String>(); { map.put(1, "jay"); map.put(2, "tianluo"); } public static void main(String[] args) { map = Collections.unmodifiableMap(map); map.put(1, "boy"); System.out.println(map.get(1)); }}运行结果: // 可以发现,unmodifiableMap确保集合不能修改啦,抛异常了Exception in thread "main" java.lang.UnsupportedOperationException at java.util.Collections$UnmodifiableMap.put(Collections.java:1457) at Test.main(Test.java:14)22. 快速失败(fail-fast)和安全失败(fail-safe)的区别是什么?快速失败在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的内容进行了修改(增加、删除、修改),则会抛出Concurrent Modification Exception。 public class Test { public static void main(String[] args) { List<Integer> list = new ArrayList<>(); list.add(1); list.add(2); Iterator iterator = list.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); list.add(3); System.out.println(list.size()); } }}运行结果: 1Exception in thread "main" java.util.ConcurrentModificationException3 at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909) at java.util.ArrayList$Itr.next(ArrayList.java:859) at Test.main(Test.java:12)安全失败采用安全失败机制的集合容器,在遍历时不是直接在集合内容上访问的,而是先复制原有集合内容,在拷贝的集合上进行遍历。 public class Test { public static void main(String[] args) { List<Integer> list = new CopyOnWriteArrayList<>(); list.add(1); list.add(2); Iterator iterator = list.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); list.add(3); System.out.println("list size:"+list.size()); } }}运行结果: 1list size:32list size:4其实,在java.util.concurrent 并发包的集合,如 ConcurrentHashMap, CopyOnWriteArrayList等,默认为都是安全失败的。 23. 什么是Java优先级队列(Priority Queue)?优先队列PriorityQueue是Queue接口的实现,可以对其中元素进行排序
方法: peek()//返回队首元素poll()//返回队首元素,队首元素出队列add()//添加元素size()//返回队列元素个数isEmpty()//判断队列是否为空,为空返回true,不空返回false特点:
24. JAVA8的ConcurrentHashMap为什么放弃了分段锁,有什么问题吗,如果你来设计,你如何设计。jdk8 放弃了分段锁而是用了Node锁,减低锁的粒度,提高性能,并使用CAS操作来确保Node的一些操作的原子性,取代了锁。 可以跟面试官聊聊悲观锁和CAS乐观锁的区别,优缺点哈~ 25. 阻塞队列的实现,ArrayBlockingQueue的底层实现?ArrayBlockingQueue是数组实现的线程安全的有界的阻塞队列,继承自AbstractBlockingQueue,间接的实现了Queue接口和Collection接口。底层以数组的形式保存数据(实际上可看作一个循环数组)。常用的操作包括 add ,offer,put,remove,poll,take,peek。 可以结合线程池跟面试官讲一下哦~ 26. Java 中的 LinkedList是单向链表还是双向链表?哈哈,看源码吧,是双向链表 private static class Node<E> { E item; Node<E> next; Node<E> prev; Node(Node<E> prev, E element, Node<E> next) { this.item = element; this.next = next; this.prev = prev; } }27. 说一说ArrayList 的扩容机制吧ArrayList扩容的本质就是计算出新的扩容数组的size后实例化,并将原有数组内容复制到新数组中去。 public boolean add(E e) { //扩容 ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } private void ensureCapacityInternal(int minCapacity) { ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));}private static int calculateCapacity(Object[] elementData, int minCapacity) { //如果传入的是个空数组则最小容量取默认容量与minCapacity之间的最大值 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { return Math.max(DEFAULT_CAPACITY, minCapacity); } return minCapacity; } private void ensureExplicitCapacity(int minCapacity) { modCount++; // 如果最小需要空间比elementData的内存空间要大,则需要扩容 // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); } private void grow(int minCapacity) { // 获取elementData数组的内存空间长度 int oldCapacity = elementData.length; // 扩容至原来的1.5倍 int newCapacity = oldCapacity + (oldCapacity >> 1); //校验容量是否够 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; //若预设值大于默认的最大值,检查是否溢出 if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // 调用Arrays.copyOf方法将elementData数组指向新的内存空间 //并将elementData的数据复制到新的内存空间 elementData = Arrays.copyOf(elementData, newCapacity); }28. HashMap 的长度为什么是2的幂次方,以及其他常量定义的含义~为了能让HashMap存取高效,数据分配均匀。 看着呢,以下等式相等,但是位移运算比取余效率高很多呢~ hash%length=hash&(length-1)29. ConcurrenHashMap 原理?1.8 中为什么要用红黑树?聊到ConcurrenHashMap,需要跟面试官聊到安全性,分段锁segment,为什么放弃了分段锁,与及选择CAS,其实就是都是从效率和安全性触发,嘻嘻~ java8不是用红黑树来管理hashmap,而是在hash值相同的情况下(且重复数量大于8),用红黑树来管理数据。红黑树相当于排序数据。可以自动的使用二分法进行定位。性能较高。30. ArrayList的默认大小ArrayList 的默认大小是 10 个元素 /** * Default initial capacity. */private static final int DEFAULT_CAPACITY = 10;31. 为何Collection不从Cloneable和Serializable接口继承?
32. Enumeration和Iterator接口的区别?public interface Enumeration<E> { boolean hasMoreElements(); E nextElement();}public interface Iterator<E> { boolean hasNext(); E next(); void remove();}
33. 我们如何对一组对象进行排序?可以用 Collections.sort()+ Comparator.comparing(),因为对对象排序,实际上是对对象的属性排序哈~ public class Student { private String name; private int score; public Student(String name, int score){ this.name = name; this.score = score; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getScore() { return score; } public void setScore(int score) { this.score = score; } @Override public String toString() { return "Student: " + this.name + " 分数:" + Integer.toString( this.score ); }}public class Test { public static void main(String[] args) { List<Student> studentList = new ArrayList<>(); studentList.add(new Student("D", 90)); studentList.add(new Student("C", 100)); studentList.add(new Student("B", 95)); studentList.add(new Student("A", 95)); Collections.sort(studentList, Comparator.comparing(Student::getScore).reversed().thenComparing(Student::getName)); studentList.stream().forEach(p -> System.out.println(p.toString())); }}34. 当一个集合被作为参数传递给一个函数时,如何才可以确保函数不能修改它?这个跟之前那个不可变集合一样道理哈~
35. 说一下HashSet的实现原理?
看看它的add方法吧~ public boolean add(E e) { return map.put(e, PRESENT)==null; }36. Array 和 ArrayList 有何区别?
37. 为什么HashMap中String、Integer这样的包装类适合作为key?String、Integer等包装类的特性能够保证Hash值的不可更改性和计算准确性,能够有效的减少Hash碰撞的几率~ 因为
38. 如果想用Object作为hashMap的Key?;重写hashCode()和equals()方法啦~ (这个答案来自互联网哈~)
39. 讲讲红黑树的特点?
40. Java集合类框架的最佳实践有哪些?其实这些点,结合平时工作,代码总结讲出来,更容易吸引到面试官呢 (这个答案来自互联网哈~)
41.谈谈线程池阻塞队列吧~
ArrayBlockingQueue: (有界队列)是一个用数组实现的有界阻塞队列,按FIFO排序量。 LinkedBlockingQueue: (可设置容量队列)基于链表结构的阻塞队列,按FIFO排序任务,容量可以选择进行设置,不设置的话,将是一个无边界的阻塞队列,最大长度为Integer.MAX_VALUE,吞吐量通常要高于ArrayBlockingQuene;newFixedThreadPool线程池使用了这个队列 DelayQueue:(延迟队列)是一个任务定时周期的延迟执行的队列。根据指定的执行时间从小到大排序,否则根据插入到队列的先后排序。newScheduledThreadPool线程池使用了这个队列。 PriorityBlockingQueue:(优先级队列)是具有优先级的无界阻塞队列; SynchronousQueue:(同步队列)一个不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQuene,newCachedThreadPool线程池使用了这个队列。针对面试题:线程池都有哪几种工作队列? 我觉得,回答以上几种ArrayBlockingQueue,LinkedBlockingQueue,SynchronousQueue等,说出它们的特点,并结合使用到对应队列的常用线程池(如newFixedThreadPool线程池使用LinkedBlockingQueue),进行展开阐述, 就可以啦。 42. HashSet和TreeSet有什么区别?
43. Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()?元素重复与否是使用equals()方法进行判断的,这个可以跟面试官说说==和equals()的区别,hashcode()和equals 44. 说出ArrayList,LinkedList的存储性能和特性这道面试题,跟ArrayList,LinkedList,就是换汤不换药的~
45. HashMap在JDK1.7和JDK1.8中有哪些不同?互联网上这个答案太详细啦(https://www.jianshu.com/p/939b8a672070) 46. ArrayList集合加入1万条数据,应该怎么提高效率
47. 如何对Object的list排序看例子吧,哈哈,这个跟对象排序也是一样的呢~ public class Person { private String name; private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Person(String name, Integer age) { this.name = name; this.age = age; }}public class Test { public static void main(String[] args) { List<Person> list = new ArrayList<>(); list.add(new Person("jay", 18)); list.add(new Person("tianLuo", 10)); list.stream().forEach(p -> System.out.println(p.getName()+" "+p.getAge())); // 用comparing比较对象属性 list.sort(Comparator.comparing(Person::getAge)); System.out.println("排序后"); list.stream().forEach(p -> System.out.print(p.getName()+" "+p.getAge()+" ")); }}48. ArrayList 和 HashMap 的默认大小是多数?在 Java 7 中,ArrayList 的默认大小是 10 个元素,HashMap 的默认大小是16个元素(必须是2的幂)。 49. 有没有有顺序的Map实现类,如果有,他们是怎么保证有序的
50. HashMap是怎么解决哈希冲突的
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 1:55:54- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |