JAVA面试题整理-基础
Posted chwilliam85
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA面试题整理-基础相关的知识,希望对你有一定的参考价值。
1、List 和 Set 的区别
共同点:它们都是Collection的子接口
区别:
List:这个接口能够精准的记录每一个元素的插入位置(换句话说就是这个接口内容所有元素是按照顺序去保存的),使用者可以通过索引的方式去取得某个元素的值,这个跟java中数组有点类似,List中保存的所有数据允许重复。
Set:这个接口无法记录每一个元素的具体位置,整个集合中所有元素是无序排列的,并且Set存储数据集合是不允许有重复的元素的。
既然List和Set均为接口,那么就不能直接实例化,需要借助实现他们接口的子类进行实例化,由此来使用接口中提供的各种方法。
实现List接口的子类中包括:ArrayList,LinkedList和Vector。
其中ArrayList这个类是类似数组形式的集合实例化,而LinkedList类则是链表形式的实例化,具体的差别在于数据结构上面的不同。
Vector 类非常类似ArrayList,两者的不同之处在于Vector是同步的方法,在多线程操作的时候可能会抛出ConcurrentModificationException。
实现Set接口的子类中包括:HasSet。
2、HashSet 是如何保证不重复的
根据HashSet.add(E e)的JDK源码,发现HashSet竟然是借助HashMap来实现的,利用HashMap中Key的唯一性,来保证HashSet中不出现重复值。
当调用add(E e)方法时候,首先会调用Object的hashCode方法判hashCode是否已经存在,如不存在则直接插入元素;
如果已存在则调用Object对象的equals方法判断是否返回true,如果为true则说明元素已经存在,如为false则插入元素。
public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable { static final long serialVersionUID = -5024744406713321676L; private transient HashMap<E,Object> map; // Dummy value to associate with an Object in the backing Map private static final Object PRESENT = new Object(); /** * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has * default initial capacity (16) and load factor (0.75). */ public HashSet() { map = new HashMap<>(); } public HashSet(Collection<? extends E> c) { map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16)); addAll(c); } public HashSet(int initialCapacity, float loadFactor) { map = new HashMap<>(initialCapacity, loadFactor); } public HashSet(int initialCapacity) { map = new HashMap<>(initialCapacity); } HashSet(int initialCapacity, float loadFactor, boolean dummy) { map = new LinkedHashMap<>(initialCapacity, loadFactor); } public Iterator<E> iterator() { return map.keySet().iterator(); } public int size() { return map.size(); } public boolean isEmpty() { return map.isEmpty(); } public boolean contains(Object o) { return map.containsKey(o); } public boolean add(E e) { return map.put(e, PRESENT)==null; } public boolean remove(Object o) { return map.remove(o)==PRESENT; } public void clear() { map.clear(); } public Object clone() { try { HashSet<E> newSet = (HashSet<E>) super.clone(); newSet.map = (HashMap<E, Object>) map.clone(); return newSet; } catch (CloneNotSupportedException e) { throw new InternalError(); } } private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { // Write out any hidden serialization magic s.defaultWriteObject(); // Write out HashMap capacity and load factor s.writeInt(map.capacity()); s.writeFloat(map.loadFactor()); // Write out size s.writeInt(map.size()); // Write out all elements in the proper order. for (E e : map.keySet()) s.writeObject(e); } private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { // Read in any hidden serialization magic s.defaultReadObject(); // Read in HashMap capacity and load factor and create backing HashMap int capacity = s.readInt(); float loadFactor = s.readFloat(); map = (((HashSet)this) instanceof LinkedHashSet ? new LinkedHashMap<E,Object>(capacity, loadFactor) : new HashMap<E,Object>(capacity, loadFactor)); // Read in size int size = s.readInt(); // Read in all elements in the proper order. for (int i=0; i<size; i++) { E e = (E) s.readObject(); map.put(e, PRESENT); } } }
/** * Associates the specified value with the specified key in this map. * If the map previously contained a mapping for the key, the old * value is replaced. * * @param key key with which the specified value is to be associated * @param value value to be associated with the specified key * @return the previous value associated with <tt>key</tt>, or * <tt>null</tt> if there was no mapping for <tt>key</tt>. * (A <tt>null</tt> return can also indicate that the map * previously associated <tt>null</tt> with <tt>key</tt>.) */ public V put(K key, V value) { if (table == EMPTY_TABLE) { inflateTable(threshold); } if (key == null) return putForNullKey(value); int hash = hash(key); int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, key, value, i); return null; }
3、HashMap 是线程安全的吗,为什么不是线程安全的(最好画图说明多线程环境下不安全)?
参考:http://www.importnew.com/22011.html
4、HashMap 的扩容过程
5、HashMap 1.7 与 1.8 的 区别,说明 1.8 做了哪些优化,如何优化的?
6、final finally finalize
7、强引用 、软引用、 弱引用、虚引用
8、Java反射
9、Arrays.sort 实现原理和 Collection 实现原理
10、LinkedHashMap的应用
11、cloneable接口实现原理
12、异常分类以及处理机制
13、wait和sleep的区别
14、数组在内存中如何分配
答案待补充... ...
以上是关于JAVA面试题整理-基础的主要内容,如果未能解决你的问题,请参考以下文章