Java 最全面的集合框架体系详细版

什么是集合?

用于存储数据的容器框架。 集合框架是为表示和操作集合而规定的一种统一的标准的体系结构。
任何集合框架都包含三大块内容:
对外的接口
接口的实现
集合运算的算法

使用集合的好处?

容量自增长;
提供了高性能的数据结构和算法,使编码更轻松,提高了程序速度和质量;
允许不同 API (应用程序编程接口)之间的互操作,API之间可以来回传递集合;
可以方便地扩展或改写集合,提高代码复用性和可操作性。
通过使用JDK自带的集合类,可以降低代码维护和学习新API成本。

常用的集合类有哪些?

Collection接口的子接口包括:List接口和Set接口
List接口的实现类主要有:Vector、ArrayList、LinkedList等
Set接口的实现类主要有:HashSet、LinkedHashSet、TreeSet等
Map接口的实现类主要有:HashMap、HashTable、TreeMap、ConcurrentHashMap等
在这里插入图片描述

集合框架底层数据结构

(1)Collection

List
有序,可以重复,
可以插入多个null元素,元素都有索引
ArraylistObject数组,连续空间(适合查改)
VectorObject数组,arraylist多了个同步化机制(线程安全),效率较低
LinkedList双向循环链表,链式空间(适合增删)
Set
只允许存入一个null元素,必须保证元素唯一性
HashSet (无序,唯一)基于 HashMap 实现的,底层采用 HashMap 来保存元素
LinkedHashSet LinkedHashSet 继承与 HashSet,并且其内部是通过 LinkedHashMap 来实现的。有点类似于我们之前说的LinkedHashMap 其内部是基于 HashMap 实现一样,不过还是有一点点区别的
TreeSet (有序,唯一)红黑树(自平衡的排序二叉树。

(2)Map

HashMap 线程不安全(如果你要保证线程安全的话就使用 ConcurrentHashMap 吧!)(适合插入、删除、定位)
LinkedHashMap LinkedHashMap 继承自 HashMap,LinkedHashMap 在上面结构的基础上,增加了一条双向链表,使得上面的结构可以保持键值对的插入顺序。同时通过对链表进行相应的操作,实现了访问顺序相关逻辑。
HashTable 线程安全
TreeMap 红黑树(自平衡的排序二叉树)(适合遍历)

List 、Set 、Map的区别?List、Map、Set 三个接口存取元素时,各有什么特点?

在这里插入图片描述

Collection 和 Collections 有什么区别?

Collection:是集合框架的顶级接口
Collections:只是一个工具类,用来操作Collection集合

哪些集合类是线程安全的?

vector: 就比arraylist多了个同步化机制(线程安全),因为效率较低,现在已经不太建议使用。在web应用中,特别是前台页面,往往效率(页面响应速度)是优先考虑的。
statck:堆栈类,先进后出。
hashtable: 就比hashmap多了个线程安全。
enumeration:枚举,相当于迭代器。

Array 和 ArrayList 有何区别?

Array 可以存储基本数据类型和对象,ArrayList 只能存储对象。
Array 是指定固定大小的,而 ArrayList 大小是自动扩展的。
Array 内置方法没有 ArrayList 多,比如 addAll、removeAll、iteration 等方法只有 ArrayList 有。

插入数据时,ArrayList、LinkedList、Vector谁速度较快?阐述 ArrayList、Vector、LinkedList 的存储性能和特性?

ArrayList 和Vector他们底层的实现都是一样的,都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢适合查改

Vector中的方法由于添加了synchronized修饰,因此Vector是线程安全的容器,但性能上较ArrayList差,因此已经是Java中的遗留容器。

LinkedList使用双向链表存储(将内存中零散的内存单元通过附加的引用关联起来,形成一个可以按序号索引的线性结构,这种链式存储方式与数组的连续存储方式相比,内存的利用率更高),按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快
例如像下面这样:

	List<String> synchronizedList = Collections.synchronizedList(list);
	synchronizedList.add("aaa");
	synchronizedList.add("bbb");
	for (int i = 0; i < synchronizedList.size(); i++) {
    System.out.println(synchronizedList.get(i));
	}

说一下 HashSet 的实现原理?

HashSet 是基于 HashMap 实现的,HashSet 底层使用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,相关 HashSet 的操作,
基本上都是直接调用底层 HashMap 的相关方法来完成 ,HashSet 不允许重复的值。

HashSet如何检查重复?HashSet是如何保证数据不可重复的?

向HashSet 中 add () 时,判断元素是否存在的依据,不仅要比较hash值,同时还要结合equles 方法比较。
HashSet 中的add ()方法会使用HashMap 的put()方法
HashMap 的 key 是唯一的,由源码可以看出 HashSet 添加进去的值就是作为HashMap 的key,并且在HashMap中如果K/V相同时,会用新的V覆盖掉旧的V,然后返回旧的V。所以不会重复( HashMap 比较key是否相等是先比较hashcode 再比较equals )。
以下是HashSet 部分源码:

	private static final Object PRESENT = new Object();
	private transient HashMap<E,Object> map;
	public HashSet() {
	    map = new HashMap<>();
	}
	public boolean add(E e) {
	    // 调用HashMap的put方法,PRESENT是一个至始至终都相同的虚值
		return map.put(e, PRESENT)==null;
	}

说一下 HashMap 的实现原理?

HashMap 基于 Hash 算法实现的,我们通过 put(key,value) 存储,get(key) 来获取。当传入 key 时,HashMap 会根据 key. hashCode() 计算出 hash 值,
根据 hash 值将 value 保存在 bucket 里。当计算出的 hash 值相同时,我们称之为 hash 冲突,HashMap 的做法是用链表和红黑树存储相同 hash 值的 value。
当 hash 冲突的个数比较少时,使用链表否则使用红黑树。

如何实现数组和 List 之间的转换?

数组转 List: 使用 Arrays. asList(array) 进行转换。
List 转数组: 使用 List 自带的 toArray() 方法。

在 Queue 中 poll()和 remove()有什么区别?

相同点: 都是返回第一个元素,并在队列中删除返回的对象。
不同点: 如果没有元素 poll()会返回 null,而 remove()会直接抛出NoSuchElementException 异常。

迭代器 Iterator 是什么?

Iterator 接口提供遍历任何 Collection 的接口。我们可以从一个 Collection 中使用迭代器方法来获取迭代器实例。
迭代器取代了 Java 集合框架中的 Enumeration,迭代器允许调用者在迭代过程中移除元素。

Iterator 怎么使用?有什么特点?

Iterator 使用代码如下:

List<String> list = new ArrayList<>();
Iterator<String> it = list. iterator();
while(it. hasNext()){
 		String obj = it. next();
 		System. out. println(obj);
}

Iterator 的特点是更加安全,因为它可以确保,在当前遍历的集合元素被更改的时候,就会抛出 ConcurrentModificationException 异常。(当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常)

Iterator 和 ListIterator 有什么区别?

Iterator 可以遍历 Set 和 List 集合,而 ListIterator 只能遍历 List。
Iterator 只能单向遍历,而 ListIterator 可以双向遍历(向前/后遍历)。
ListIterator 从 Iterator 接口继承,然后添加了一些额外的功能,比如添加一个元素、替换一个元素、获取前面或后面元素的索引位置。

怎么快速遍历Map集合?

Map.entryset()

ConcarrentHashMap与HashMap的区别是什么?

concarrentHashMap:采用了分段锁技术(默认效率提升16倍)【分段锁技术:可以理解为把一个大的Map拆分成N个小的HashTable,根据key.hashcode()来决定把key放到哪个HashTable中去】,在性能上比HashMap高16倍,同时线程安全

怎么确保一个集合不能被修改?

可以使用Collections. unmodifiableCollection(Collection c) 方法来创建一个只读集合,这样改变集合的任何操作都会抛出 Java. lang. UnsupportedOperationException 异常(不支持功能异常)。

	List<String> list = new ArrayList<>();
	list. add("x");
	Collection<String> clist = Collections. unmodifiableCollection(list);
	clist. add("y"); // 运行时此行报错
	System. out. println(list. size());

JAVA中List集合,Set集合,Map集合遍历的方法

public static void main(String[] args) {
  /**
  List集合中的3种遍历方法 
  **/
   List<String> names=new ArrayList<String>();
   names.add("tom");
   names.add("jim");
   names.add("lucy");
 
   //法1:传统for循环,
    for(int i=0;i<names.size();i++) {    
        String name1=names.get(i);    
       System.out.println(name1);
   }
   //法2,加强for循环。
    for(String n:names) {
       System.out.println(n);
    }
   //法3,迭代器
    Iterator<String> iterator=names.iterator();    
    while(iterator.hasNext()) {        //判断容器中是否有值
        String value=iterator.next();
        System.out.println(value);
    }    


  /**
   Set集合中的2种遍历方法
  **/
    Set<Integer> scores=new HashSet<Integer>()
    scores.add(1);
    scores.add(3);
    scores.add(7);
  
   //法1,
    for(int score:scores) {
        System.out.println(score);
    }
    
    //法2,
    Iterator<Integer> iterator=scores.iterator();
 	   while(iterator.hasNext()) {
       int value=iterator.next();
       System.out.println(value);
   }


   /**
   Map集合中的4种遍历方法。
   **/
    Map<String,Integer> scores=new HashMap<String,Integer>();
    
    scores.put("tom", 111);    
    scores.put("lucy", 222);
    Set<String> keys=scores.keySet();

    //法1,加强for循环
   for(String key:keys) {
        //System.out.println(key);
        int s=scores.get(key);
        System.out.println(s);
    }
    
    //法2,迭代器
    Iterator<String> iterator=keys.iterator();
    while(iterator.hasNext()) {
        String key=iterator.next();
        //System.out.println(key);
        int value=scores.get(key);    
        System.out.println(value);
    }
    //法3,
    Set<Entry<String,Integer>> set=scores.entrySet();
    for(Entry<String,Integer> entry:set) {
        String key=entry.getKey();
        Integer value=entry.getValue();
        System.out.println(key+":"+value);
    }
    //法4,
    Iterator<Entry<String,Integer>> iterator=set.iterator();
    while(iterator.hasNext()) {
        Entry<String, Integer> entry=iterator.next();
        String key=entry.getKey();
        Integer value=entry.getValue();
        System.out.println(key+":"+value);
    }

}

1


  1. 编写不易,如果有帮助到的话,可以关注,点赞和收藏哦~ ↩︎

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值