Java面试一

xiaoxiao2021-02-28  26

基础一

知识点一

集合类:List和Set比较,各自的子类比较(ArrayList,Vector,LinkedList;HashSet,TreeSet)。 ArrayList : 列表,可以说是动态数组;有序的,可以重复的;非线程安全。 LinkedList : 双向列表,可以根据下个节点访问上一个节点;有序的,可以重复的;线程安全。 Vector : 有序的,可以重复的;线程安全。 HashSet: 不可重复,无序的。 TreeSet : 有序的,不可重复。HashMap的底层实现,之后会问ConcurrentHashMap的底层实现。 HashMap:本质是数组链表,Key.hashCode()做主键。Key-Value的对象。HashMap是非线程安全的。 ConcurrentHashMap在线程安全的基础上提供了更好的写并发能力,但同时降低了对读一致性的要求。 LinkedHashMap 与 LRUcache: LRU 缓存利用了这样的一种思想。LRU 是 Least Recently Used 的缩写,翻译过来就是“最近最少使用”,也就是说,LRU 缓存把最近最少使用的数据移除,让给最新读取的数据。而往往最常读取的,也是读取次数最多的,所以,利用 LRU 缓存,我们能够提高系统的 performance。 import java.util.LinkedHashMap; import java.util.Collection; import java.util.Map; import java.util.ArrayList; /** * An LRU cache, based on <code>LinkedHashMap</code>. * * <p> * This cache has a fixed maximum number of elements (<code>cacheSize</code>). * If the cache is full and another entry is added, the LRU (least recently * used) entry is dropped. * * <p> * This class is thread-safe. All methods of this class are synchronized. * * <p> * Author: Christian d'Heureuse, Inventec Informatik AG, Zurich, Switzerland<br> * Multi-licensed: EPL / LGPL / GPL / AL / BSD. */ public class LRUCache<K, V> { private static final float hashTableLoadFactor = 0.75f; private LinkedHashMap<K, V> map; private int cacheSize; /** * Creates a new LRU cache. 在该方法中,new LinkedHashMap<K,V>(hashTableCapacity, * hashTableLoadFactor, true)中,true代表使用访问顺序 * * @param cacheSize * the maximum number of entries that will be kept in this cache. */ public LRUCache(int cacheSize) { this.cacheSize = cacheSize; int hashTableCapacity = (int) Math .ceil(cacheSize / hashTableLoadFactor) + 1; map = new LinkedHashMap<K, V>(hashTableCapacity, hashTableLoadFactor, true) { // (an anonymous inner class) private static final long serialVersionUID = 1; @Override protected boolean removeEldestEntry(Map.Entry<K, V> eldest) { return size() > LRUCache.this.cacheSize; } }; } /** * Retrieves an entry from the cache.<br> * The retrieved entry becomes the MRU (most recently used) entry. * * @param key * the key whose associated value is to be returned. * @return the value associated to this key, or null if no value with this * key exists in the cache. */ public synchronized V get(K key) { return map.get(key); } /** * Adds an entry to this cache. The new entry becomes the MRU (most recently * used) entry. If an entry with the specified key already exists in the * cache, it is replaced by the new entry. If the cache is full, the LRU * (least recently used) entry is removed from the cache. * * @param key * the key with which the specified value is to be associated. * @param value * a value to be associated with the specified key. */ public synchronized void put(K key, V value) { map.put(key, value); } /** * Clears the cache. */ public synchronized void clear() { map.clear(); } /** * Returns the number of used entries in the cache. * * @return the number of entries currently in the cache. */ public synchronized int usedEntries() { return map.size(); } /** * Returns a <code>Collection</code> that contains a copy of all cache * entries. * * @return a <code>Collection</code> with a copy of the cache content. */ public synchronized Collection<Map.Entry<K, V>> getAll() { return new ArrayList<Map.Entry<K, V>>(map.entrySet()); } // Test routine for the LRUCache class. public static void main(String[] args) { LRUCache<String, String> c = new LRUCache<String, String>(3); c.put("1", "one"); // 1 c.put("2", "two"); // 2 1 c.put("3", "three"); // 3 2 1 c.put("4", "four"); // 4 3 2 if (c.get("2") == null) throw new Error(); // 2 4 3 c.put("5", "five"); // 5 2 4 c.put("4", "second four"); // 4 5 2 // Verify cache content. if (c.usedEntries() != 3) throw new Error(); if (!c.get("4").equals("second four")) throw new Error(); if (!c.get("5").equals("five")) throw new Error(); if (!c.get("2").equals("two")) throw new Error(); // List cache content. for (Map.Entry<String, String> e : c.getAll()) System.out.println(e.getKey() + " : " + e.getValue()); } } 如何实现HashMap顺序存储:可以参考LinkedHashMap的底层实现。 双向链表,详细参考http://wiki.jikexueyuan.com/project/java-collection/linkedhashmap.htmlHashTable和ConcurrentHashMap的区别。 HashTable不能包含null,HashMap可以包含null。虽然HashTable和ConcurrentHashMap都是线程安全的。但是HashTable是使用synchronized;ConcurrentHashMap使用分段锁实现,称为Segment;ConcurrentHashMap内部拥有一个Entry数组,数组中的每个元素又是一个链表;同时又是一个ReentrantLock(Segment继承了ReentrantLock)。ConcurrentHashMap中的HashEntry相对于HashMap中的Entry有一定的差异性:HashEntry中的value以及next都被volatile修饰,这样在多线程读写过程中能够保持它们的可见性。 static final class HashEntry<K,V> { final int hash; final K key; volatile V value; volatile HashEntry<K,V> next; String,StringBuffer和StringBuilder的区别。 StringBuffer、StringBuilder和String一样,也用来代表字符串。String类是不可变类,任何对String的改变都 会引发新的String对象的生成;StringBuffer则是可变类,任何对它所指代的字符串的改变都不会产生新的对象。既然可变和不可变都有了,为何还有一个StringBuilder呢?相信初期的你,在进行append时,一般都会选择StringBuffer吧! 先说一下集合的故事,HashTable是线程安全的,很多方法都是synchronized方法,而HashMap不是线程安全的,但其在单线程程序中的性能比HashTable要高。StringBuffer和StringBuilder类的区别也是如此,他们的原理和操作基本相同,区别在于StringBufferd支持并发操作,线性安全的,适 合多线程中使用。StringBuilder不支持并发操作,线性不安全的,不适合多线程中使用。新引入的StringBuilder类不是线程安全的,但其在单线程中的性能比StringBuffer高。Object的方法有哪些:比如有wait方法,为什么会有?wait和sleep的区别? 有getClass(),equals(),hashCode(),toString(),notify(),notifyAll()。 在java.lang.Thread类中,提供了sleep(),而java.lang.Object类中提供了wait(), notify()和notifyAll()方法来操作线程 sleep()可以将一个线程睡眠,参数可以指定一个时间。而wait()可以将一个线程挂起,直到超时或者该线程被唤醒。wait有两种形式wait()和wait(milliseconds)。JVM的内存结构,JVM的算法。

具体划分为如下5个内存空间:(非常重要)

栈:存放局部变量 堆:存放所有new出来的东西 方法区:被虚拟机加载的类信息、常量、静态常量等。 程序计数器(和系统相关) 本地方法栈


知识点二

强引用,软引用和弱引用的区别。

1) 强引用:就是正常的引用。 GC是不会清理一个强引用引用的对象的,即使面临内存溢出的情况。

String str = "abc"; List<String> list = new Arraylist<String>(); list.add(str); //在list集合里的数据不会释放,即使内存不足也不会

2) 软引用:SoftReference。 GC会在内存不足的时候清理引用的对象:

SoftReference reference = new SoftReference(object); object = null;

3) 弱引用:GC线程会直接清理弱引用对象,不管内存是否够用。

WeakReference reference = new WeakReference(object); object = null;

4) 虚引用:和弱引用一样,会直接被GC清理,而且通过虚引用的get方法不会得到对象的引用,形同虚设,这里弱引用是可以的。

PhantomReference refernce = new PhantomReference(object); object = null;
数组在内存中如何分配。

比如int[] arr=new int[3]; 栈中为arr分配一个存储单位,存储的是指向一个新创建的数组的引用,该地址指向数组对象。

转载请注明原文地址: https://www.6miu.com/read-2624972.html

最新回复(0)