云计算百科
云计算领域专业知识百科平台

【Java八股 | 集合篇】概念类(数组和集合的区别、集合、线程安全的集合、集合遍历方法、Collection和Collections)

概念类

一、数组和集合的区别

        1.长度:数组长度是固定的,一旦创建无法改变;集合长度可变,可随时动态增删元素

        2.存储内容:数组可以存储基本类型和引用类型;集合只能存储引用类型

        3.类型限制:数组只能存储同一种类型的元素;集合不指定泛型可以存储任意对象,加泛型后可以限制存储类型

二、Java中的集合

        Java集合的核心是CollectionMap两大根接口,它们最本质的区别是Collection存的是单个元素,而Map存的是Key-Value形式的键值对

        集合的三个派系为List、Set和Map

        List:有序的、可重复的,按照插入顺序保存,通过索引(下表)访问,允许元素重复,主要实现类有ArrayListLinkedList

        ArrayList:底层为动态数组,查询快(随机访问)但增删慢(需要移动元素),适合读多写少。

        LinkedList:底层为双向链表,查询慢(需要便利)但增删快(只改指针),适合写多都少。

        Set:无序,不可重复,不允许重复元素,无序是指不保证插入顺序,没有索引。常见实现类有HashSetTreeSetLinkedHashSet

         HashSet:基于HashMap实现,HashMap的Key即HashSet存储的元素,利用哈市Code()和equels()保证唯一性。

         TreeSet:基于TreeMap实现,用的红黑树结构,会按照元素大小自动排序。

         LinkedHashSet:继承自HashSet,使用双向链表维护元素插入顺序

        Map:键值对,键唯一。Key唯一,Value可重复。主要实现由HashMap、LinkedHashMap、TreeMap、和Hashtable

        HashMap:JDK1.8后底层为数组+链表+红黑树。当链表长度大于阈值(默认为8)时,链表会转化为红黑树来提高查询效率。

        LinkedHashMap:继承自HashMap,增加了一条双向链表,保证了键值对的插入顺序。

        Hashtable:数组+链表组成的,数组是 HashTable 的主体,链表则是主要为了解决哈希冲突而存在的。

        TreeMap:红黑树,自平衡的二叉查找树,自动排序(按Key排序)。

三、Java中线程安全的集合

        Java.util包中线程安全的主要有两个。线程安全,但性能低下。(旧版)

        Vector:线程安全的动态数组,内部方法基本都经过synchronized修饰。

        Hashtable:线程安全的哈希表,HashTable 的加锁方法是给每个方法加上 synchronized 关键字。

        java.util.concurrent 包提供的都是线程安全的集合:

        1.并发List:

        CopyOnWriteArrayList:写时复制,写加锁,读不加锁,适合读多写少

        写操作:

                1.加锁,保证只有一个线程

                2.复制一份新数组

                3.在新数组中修改

                4.把引用指向新数组

        读操作:不加锁,直接读。

        2.并发Set:

        CopyOnWriteArraySet:底层就是CopyOnWriteArrayList,线程安全,适合读多写少

        ConcurrentSkipListSet:是线程安全的有序的集合。底层是使用ConcurrentSkipListMap实现。

        3.并发Map:

        ConcurrentHashMap:

        JDK7以前加的是分段锁Sement(默认16段),每段一把锁,支持16个线程并发写。

        JDK8以后取消了分段锁Sement。

        结构为数组+链表+红黑树。

                数组:table,真正存数据。

                链表:哈希冲突时拉链。

                红黑树:链表太长时优化查询。链表长度≥8且数组长度≥64–>红黑树。树节点≤6–>链表

         线程安全的实现:

                 数组位置为时,用CAS尝试插入,不加锁;不为空,用synchronized链表/树的头节点。   

        ConcurrentSkipListMap:实现了一个基于SkipList(跳表)算法的可排序的并发集合,SkipList是一种可以在对数预期时间内完成搜索、插入、删除等操作的数据结构,通过维护多个指向其他元素的“跳跃”链接来实现高效查找。

四、Collections和Collection的区别

        Collection是一个接口,它是所有集合类的基础接口。它定义了一组通用的操作和方法,如添加、删除、遍历等,用于操作和管理一组对象。Collection接口有许多实现类,如List、Set和Queue等。

        而Collections是一个工具类,位于java.util包中。它提供了一系列静态方法,用于对集合进行操作和算法。Collections类中的方法包括排序、查找、替换、反转、随机化等等,这些方法可以对实现了Collection接口的集合进行操作,如List和Set。

五、集合的遍历方法

        1.普通for循环:可以使用带有索引的普通 for 循环来遍历 List。

import java.util.ArrayList;
import java.util.List;

public class ListForLoopExample {
public static void main(String[] args) {
// 创建并初始化一个List
List<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Orange");
fruits.add("Grape");

// 使用普通for循环遍历List
for (int i = 0; i < fruits.size(); i++) {
String fruit = fruits.get(i);
System.out.println("Fruit at index " + i + ": " + fruit);
}
}
}

        2.增强for:用于循环访问数组或集合中的元素。

import java.util.ArrayList;
import java.util.List;

public class ListForLoopExample {
public static void main(String[] args) {
// 创建并初始化一个List
List<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Orange");
fruits.add("Grape");

// 使用普通for循环遍历List
for (int i = 0; i < fruits.size(); i++) {
String fruit = fruits.get(i);
System.out.println("Fruit at index " + i + ": " + fruit);
}
}
}

        3.迭代器:可以使用迭代器来遍历集合,特别适用于需要删除元素的情况。

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class IteratorExample {
public static void main(String[] args) {
// 创建集合并添加元素
List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Orange");

// 获取迭代器
Iterator<String> iterator = list.iterator();

// 使用迭代器遍历集合
while (iterator.hasNext()) {
String element = iterator.next();
System.out.println(element);
}
}
}

        4.for-each:Java 8引入了 forEach 方法,可以对集合进行快速遍历。

import java.util.ArrayList;
import java.util.List;

public class ForEachExample {
public static void main(String[] args) {
List<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Orange");

for (String fruit : fruits) {
System.out.println(fruit);
}
}
}


赞(0)
未经允许不得转载:网硕互联帮助中心 » 【Java八股 | 集合篇】概念类(数组和集合的区别、集合、线程安全的集合、集合遍历方法、Collection和Collections)
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!