【面试】Java集合框架的基础接口有哪些?/Iterator与ListIterator有什么区别?/在Hashtable上下文中同步是什么意思?怎样使Hashmap同步?/map的遍历方式/关于for


一、Java集合框架的基础接口有哪些?

Collection为集合层级的根接口。
 一个集合表明一组对象,这些对象即为它的元素。
 Java平台不提供这个接口任何直接的实现。
Set是一个不能包含重复元素的集合。
   这个接口对数学集合抽象进行建模,被用来表明集合,就如一副牌。
List是一个有序集合,能够包含重复元素。
你能够经过它的索引来访问任何元素。List更像长度动态变换的数组。
Map是一个将key映射到value的对象.
一个Map不能包含重复的key:每一个key最多只能映射一个value。
一些其它的接口有Queue、Dequeue、SortedSet、SortedMap和ListIterator

二、Iterator与ListIterator有什么区别?

Iterator:只能正向遍历集合,只能够向前遍历,适用于获取移除元素。
ListIerator:ListIerator能够双向遍历,ListIterator从Iterator接口继承,而后添加了一些额外的功能,好比添加一个元素、替换一个元素、获取前面或后面元素的索引位置。java

咱们可使用Iterator来遍历Set和List集合,而ListIterator只能遍历List。

三、在Hashtable上下文中同步是什么意思?怎样使Hashmap同步?

同步意味着在一个时间点只能有一个线程能够修改哈希表,任何线程在执行hashtable的更新操做前须要获取对象锁,其余线程等待锁的释放。web

HashMap能够经过Map m = Collections.synchronizedMap(hashMap)来达到同步的效果。数组

四、map的遍历方式

第一种 这是最多见的用法,缓存

优势:这种用法能够同时拿到key和value值。
缺点:若是map是空,将会出现空指针异常,那么每次在对map遍历之前,就要先进行判空
public static void forEachMap(Map<String,String> map) {         
    for ( Map.Entry<String,String> entry : map.entrySet()) {    
        System.out.println(entry.getKey()+entry.getValue());    
    }                                                           
}

第二种安全

只遍历key或者value。
比第一种方法的效率略微有提高,并且代码也能简洁一点。
一样,这种方法也须要判断map是否为空数据结构

public static void forEachMap2(Map<String,String> map){     
     for (String str :map.keySet()){                         
         System.out.println(str);                            
     }                                                       
     for (String str :map.values()){                         
         System.out.println(str);                            
     }                                                       
 }

第三种多线程

使用迭代器的方式并发

public static void forEachMap1(Map<String, String> map) {                     
      Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator(); 
      while (iterator.hasNext()) {                                              
          Map.Entry<String, String> entry = iterator.next();                    
          System.out.println(entry.getKey() + entry.getValue());                
      }                                                                         
  }      
// 使用迭代器可是不适用泛型 
                                                                            
  public static void forEachMap4(Map<String, String> map) {                     
      Iterator iterator = map.entrySet().iterator();                            
      while (iterator.hasNext()){                                               
          Map.Entry entry= (Map.Entry) iterator.next();   
    //这里的类型转换的缘由是,若是不加String,那么背默认为两个object,不能相加 
          System.out.println((String)entry.getKey() + entry.getValue());        
      }                                                                         
  }

第四种框架

先拿到map的key值,再拿取value值。 这种方式效率比较低,通常不推荐使用svg

for (Integer key : map.keySet()) {  
    Integer value = map.get(key);  
    System.out.println("Key = " + key + ", Value = " + value);  
}

五、ArrayList、Vector和LinkedList有什么区别?

1.ArrayList是实现了基于动态数组的数据结构,LinkedList是基于链表结构。
2.对于随机访问的get和set方法,ArrayList要优于LinkedList,由于LinkedList要移动指针。
3.对于新增和删除操做add和remove,LinkedList比较占优点,由于ArrayList要移动数据。

LinkedList常常用在增删操做较多而查询操做不多的状况下,ArrayList则相反。

这三个类都继承自List接口,内部元素能够重复但有序。都在java.util包中,都是可伸缩的数组,也就是说能够动态改变数组的长度。

ArrayList和Vector:都是基于Object[] 对象数组实现的。它们在建立的时候会申请连续的存储空间来存储数据。总结:

他们支持使用下标来访问元素,索引数据的速度回比较快。
由于是顺序存储,插入数据的时候须要移动容器中的数据,因此对数据的插入操做效率会比较慢。

ArrayList和Vector都有一个初始化的容量值,当添加进入容易中的数据长度大于容器的长度时,它们会自动动态扩充他们的存储单元。Vector默认扩充为原来的2倍,而ArrayList扩充为原来的1.5倍。
  区别

  1. 它俩最大的区别就是同步的使用。ArrayList中的方法都是非同步的,因此ArrayList不是安全的,Vector中的大多数方法都是直接或者间接同步的,因此Vector是线程安全的。相对而言,由于Vector是线程安全,而ArrayList线程不安全,因此ArrayList性能较Vector高。

  2. LinkedList是采用双向列表实现的,对数据的索引须要从列表头开始遍历,所以用于随机访问则效率比较低。可是由于插入元素是不须要对数据进行移动,所以插入操做的效率较高。同时LinkedList是非线程安全容器。

  3. List的选择:

  • 当进行索引或在集合的末端增长和删除元素时,使用ArrayList和Vector的效率较高;

  • 当进行特定位置的插入和删除元素的操做时,LinkedList的效率较高;由于LinkedList不须要移动元素。当在多线程中使用容器时,选择Vector比较安全。由于Vector是线程安全。

六、关于foreach和iterator

foreach的语法只是对iterator进行了简单的包装,使用起来更加方便而已,可是若是在foreach循环体内,对集合元素进行删除添加操做的时候,会报出ConcurrentModificationException,并发修改异常。
若是须要在遍历集合的时候对象集合中元素进行删除操做,须要使用iterator的遍历方式,iterator自带的remove删除方式不会报出异常。

import java.util.List;
import java.util.ArrayList;
import java.util.List;
public class UseForeach {
 
	public static void main(String[] args) {
		List<String> list=new ArrayList<String>();
		//遍历集合
		list.add("abc");
		list.add("def");
		list.add("hjj");
		list.add("klm");
		list.add("nop");
		list.add("qrs");
		System.out.println("foreach example\n");
		for(String string:list) {
			System.out.println(string);
		}
		System.out.println();
		String[] strs=new String[list.size()];
		//遍历数组
		list.toArray(strs);
		for(String string:list) {
			System.out.println(string);
		}
 
	}
 
}
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
 
public class Test_1 {
 
	public Test_1() {
		// TODO Auto-generated constructor stub
	}
 
	/** * @param args */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
 
		List l = new ArrayList();
		l.add("aa");
		l.add("bb");
		l.add("cc");
		for (Iterator i = l.iterator(); i.hasNext();) {
			String str = (String) i.next();
			System.out.println(str);
 
		}
		System.out.print("\n");
		Iterator it = l.iterator();
		while (it.hasNext()) {
			String str = (String) it.next();
			System.out.println(str);
		}
	}//main
}
运行结果:
//aa
//bb
//cc
//
//aa
//bb
//cc
//

七、什么是CopyOnWriteArrayList,它与ArrayList有何不一样?

CopyOnWriteArrayList是ArrayList的一个线程安全的变体,其中全部可变操做(add、set等等)都是经过对底层数组进行一次新的复制来实现的。相比较于ArrayList它的写操做要慢一些,由于它须要实例的快照。

CopyOnWriteArrayList中写操做须要大面积复制数组,因此性能确定不好,可是读操做由于操做的对象和写操做不是同一个对象,读之间也不须要加锁,读和写之间的同步处理只是在写完后经过一个简单的"="将引用指向新的数组对象上来,这个几乎不须要时间,这样读操做就很快很安全,适合在多线程里使用,绝对不会发生ConcurrentModificationException ,所以CopyOnWriteArrayList适合使用在读操做远远大于写操做的场景里,好比缓存。

文章持续更新:欢迎各位小伙伴关注个人公众号:菜丸的程序屋。但愿将个人不足之处给予指点,谢谢你们。
在这里插入图片描述