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


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

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

2、Iterator与ListIterator有什么区别?

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

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

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

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

HashMap可以通过Map m = Collections.synchronizedMap(hashMap)来达到同步的效果。

4、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值。 这种方式效率比较低,一般不推荐使用

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

5、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是线程安全。

6、关于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
//

7、什么是CopyOnWriteArrayList,它与ArrayList有何不同?

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

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

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

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值