集合框架详解

Java 集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射

集合框架是一个用来代表和操纵集合的统一架构。所有的集合框架都包含如下内容:

  • 接口:是代表集合的抽象数据类型。例如 Collection、List、Set、Map 等。之所以定义多个接口,是为了以不同的方式操作集合对象
  • 实现(类):是集合接口的具体实现。从本质上讲,它们是可重复使用的数据结构,例如:ArrayList、LinkedList、HashSet、HashMap。
  • 算法:是实现集合接口的对象里的方法执行的一些有用的计算,例如:搜索和排序,这些算法实现了多态,那是因为相同的方法可以在相似的接口上有着不同的实现。

集合概述:类似数组的容器,只能存储引用数据类型

优点:可扩展,可以调用多种方法,存储全是引用数据类型及对象,利于面向对象编程

集合中分单列集合和双列集合:

  1. Collection是单列集合,Collection是一个接口,List接口和Set接口继承了Collection接口,ArrayList和LinkedList和Vector实现了List接口,HashSet和LinkedListSet实现了Set接口
  2. Map是双列集合,Map是一个接口,HashMap和LinkedHashMap实现了Map接口

Collection单列集合

List是线性列表的存储方式,长度可动态改变

List接口是一个有序的Collection,使用此接口可以精确的控制每个元素的插入位置,能够通过索引来访问List中的元素,第一个索引为0,可以存在相同的元素

List接口存储一组,不唯一,有序的对象

Set接口具有与Collection完全一样的接口,Set不保存重复的元素

Set接口存储一组,唯一,无序的对象

1.1. Set集合和List集合的区别

  • . Set 接口实例存储的是无序的,不重复的数据。List 接口实例存储的是有序的,可以重复的元素。
  • 2. Set 检索效率低下,删除和插入效率高,插入和删除不会引起元素位置改变 <实现类有HashSet,TreeSet>
  • 3. List 和数组类似,可以动态增长,根据实际存储的数据的长度自动增长 List 的长度。查找元素效率高,插入删除效率低,因为会引起其他元素位置改变 <实现类有ArrayList,LinkedList,Vector>

1.2. Collection集合的通用遍历方式

  1. 迭代器遍历:直接从集合中获取iterator()方法,返回一个迭代器对象
  2. hasNext()判断是否有下一个可以迭代的元素
  3. next()获取集合中的下一个元素
  4. remove()删除集合中迭代器正在遍历的元素

Map双列集合

使用key->value对的存储方式,长度可以动态改变

Map 接口存储一组键值对象,提供key(键)到value(值)的映射。

Map.Entry:描述在一个Map中的一个元素(键值对),是一个Map的内部接口

HashMap特点:元素无序,允许为空,key不能重复

List接口

List接口是Collection的子接口

List特点:有序,可重复

List中存在索引,所以可以通过索引获取List中的元素

1.1. 特有方法

List中的特有方法

add(int index,Object obj) 将指定元素插入到集合的指定位置

remove(index)删除指定索引上的元素

set(int index ,Object obj) 用指定元素替换到指定索引上原有的值

1.2. List中的特有遍历方式

通过size获取数组的长度,再通过get方法获取每个索引上对应的元素

1.3. List中的异常

ConcurrentModificationExecption:并发修改异常

避免方式:集合遍历集合修改,迭代器遍历迭代器修改

List的实现类

List是一个接口,无法直接创建对象,所以根据底层实现不同,具有不同实现类

ArrayList:数组实现,顺序存储

LinkedList:链表实现,节点存储

ArrayList

ArrayList类是一个可以动态修改的数组

ArrayList继承了AbstractList,实现了List接口

ArrayLIst查询效率高,增删效率低

import java.util.ArrayList; // 引入 ArrayList 类

ArrayList<E> objectName =new ArrayList<>();  // 初始化

  • E:泛型数据类型,用于设置objectName的数据类型,只能是引用数据类型
  • objectName:对象名

ArrayList 是一个数组队列,提供了相关的添加、删除、修改、遍历等功能。

在ArrayList中添加元素可以用add方法

在ArrayList中访问元素可以用get方法

在ArrayList中修改元素可以用set方法

在ArrayList中删除元素可以用remove方法

遍历数组

import java.util.ArrayList;

public class RunoobTest {
    public static void main(String[] args) {
        ArrayList<String> sites = new ArrayList<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Weibo");
        for (int i = 0; i < sites.size(); i++) {
            System.out.println(sites.get(i));
        }
    }
}
import java.util.ArrayList;

public class RunoobTest {
    public static void main(String[] args) {
        ArrayList<String> sites = new ArrayList<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Weibo");
        for (String i : sites) {
            System.out.println(i);
        }
    }
}
LinkedList

链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的地址。

链表可分为单向链表和双向链表。

一个单向链表包含两个值: 当前节点的值和一个指向下一个节点的链接

LinkedList:以节点实现,链式存储

LinkedList的查询速度慢,增删速度块

LinkedList的底层是双向链表,双向链表中存储了上一个节点的地址值,下一个节点的地址值,本节点的值

以下情况需要用到LinkedList

  • 你需要通过循环迭代来访问列表中的某些元素。
  • 需要频繁的在列表开头、中间、末尾等位置进行添加和删除元素操作。

LinkedList 继承了 AbstractSequentialList 类。

LinkedList 实现了 Queue 接口,可作为队列使用。

LinkedList 实现了 List 接口,可进行列表的相关操作。

LinkedList 实现了 Deque 接口,可作为队列使用。

LinkedList 实现了 Cloneable 接口,可实现克隆。

LinkedList 实现了 java.io.Serializable 接口,即可支持序列化,能通过序列化去传输。

// 引入 LinkedList 类
import java.util.LinkedList; 

LinkedList<E> list = new LinkedList<E>();   // 普通创建方法
或者
LinkedList<E> list = new LinkedList(Collection<? extends E> c); // 使用集合创建链表

因为LinkedList在增删元素方面很便捷,所以给LinkedList中提供了一些增删的方法

addFirst()将指定元素插入到列表头部

addLast()将指定元素插入到列表尾部

removeFirst()删除头部元素并返回

removeLast()删除尾部元素并返回

getFirst()返回头部元素

getLast()返回尾部元素

泛型

泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。

泛型类

带有泛型的类

格式:

class 类名 <泛型1,泛型2,泛型3>{

}

泛型方法

泛型方法,该方法在调用时可以接收不同类型的参数。根据传递给泛型方法的参数类型,编译器适当地处理每一个方法调用。

所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前,

泛型标记符:

  • E - Element (在集合中使用,因为集合中存放的是元素)
  • T - Type(Java 类)
  • K - Key(键)
  • V - Value(值)
  • N - Number(数值类型)
  • - 表示不确定的 java 类型
public class GenericMethodTest
{
   // 泛型方法 printArray                         
   public static < E > void printArray( E[] inputArray )
   {
      // 输出数组元素            
         for ( E element : inputArray ){        
            System.out.printf( "%s ", element );
         }
         System.out.println();
    }
 
    public static void main( String args[] )
    {
        // 创建不同类型数组: Integer, Double 和 Character
        Integer[] intArray = { 1, 2, 3, 4, 5 };
        Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };
        Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };
 
        System.out.println( "整型数组元素为:" );
        printArray( intArray  ); // 传递一个整型数组
 
        System.out.println( "\n双精度型数组元素为:" );
        printArray( doubleArray ); // 传递一个双精度型数组
 
        System.out.println( "\n字符型数组元素为:" );
        printArray( charArray ); // 传递一个字符型数组
    } 
}

类型通配符:

类型通配符一般是使用?代替具体的类型参数,

import java.util.*;
 
public class GenericTest {
     
    public static void main(String[] args) {
        List<String> name = new ArrayList<String>();
        List<Integer> age = new ArrayList<Integer>();
        List<Number> number = new ArrayList<Number>();
        
        name.add("icon");
        age.add(18);
        number.add(314);
 
        getData(name);
        getData(age);
        getData(number);
       
   }
 
   public static void getData(List<?> data) {
      System.out.println("data :" + data.get(0));
   }
}

因为参数是List<?>所以name,age,number 都符合参数类型都可以进行传递

import java.util.*;
 
public class GenericTest {
     
    public static void main(String[] args) {
        List<String> name = new ArrayList<String>();
        List<Integer> age = new ArrayList<Integer>();
        List<Number> number = new ArrayList<Number>();
        
        name.add("icon");
        age.add(18);
        number.add(314);
 
        //getUperNumber(name);//1
        getUperNumber(age);//2
        getUperNumber(number);//3
       
   }
 
   public static void getData(List<?> data) {
      System.out.println("data :" + data.get(0));
   }
   
   public static void getUperNumber(List<? extends Number> data) {
          System.out.println("data :" + data.get(0));
       }
}

因为参数是List<?extendsNumber>表示参数继承于Number,都是int类型,其中name是String不符合参数类型,所以getUperNumber(name)会报错

List<?extendsNumber>表示参数只能接受Number及其下层子类类型,

类型通配符下限通过形如 List<? super Number> 来定义,表示类型只能接受 Number 及其上层父类类型

Set接口

set是Collection的子接口

set的特点:

  1. 无序:存取顺序不一样
  2. 不可重复:不可存储重复的元素
  3. 没有像LinkedList集合中有索引
set的实现类

:set的实现类HashSet,TreeSet

Hashset的底层原理是哈希表

TreeSet的底层原理是二叉树

HashSet

HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合。HashSet 是无序的,即不会记录插入的顺序。

HashSet 不是线程安全的

保证唯一性的原理:需要重写HashCode和equals方法,

HashCode:区分地址值

equals:区分值

首先判断哈希值是否一致,如果一致则去重,如果不一致直接存储

然后判断值是否一致,如果不一致直接存储,如果不一致去重

HashSet的方法

  • 通过add方法添加元素
  • 通过contains来判断元素是否存在
  • 通过remove来删除元素
LinkedHashSet

LinkedHashSet是HashSet的一个子类

LinkedHashSet是有序的,存取的顺序一致,也是不可重复的


Map双列集合

Map是双列集合的顶层接口

Map描述的是一个数据(key)到另一个数据(value)的映射关系

通过key来寻找value

Map集合的特点

  1. Key是唯一的不能重复的
  2. value是不唯一的,但一个key只能对应一个value

Map的所有操作都是对应键的

1.1.Map的常用方法

在Map中添加元素用的是put方法

put(K key,V Value),将键值对添加到指定集合当中

删除元素用的是remove方法

remove(K key)并返回删除的值,如果不存在则不操作

clear():清空集合

size()返回集合中键值对的个数

get(Object key)根据键值对获取值,如果不存在则返回null

containsKey(Object key)判断集合中是否含有该键

containsValue(Object value)判断集合中是否含有该值

Map集合的遍历
  1. 使用获取Map集合中的键,放到Set集合当中,再遍历set集合取出键,根据键获取value
  • 获取Map集合当中的所有键:Set keySet()方法
  • 遍历set集合,使用for循环或者for-each循环,或迭代器遍历
  • 获取每个键后,根据键获取对应的值 V get(K key)

特点:获取键之后,还需要通过集合来获取值

  1. 获取Map集合的键值对对象(Entry),存储到Set集合当中,遍历Set集合,获取到每一个键值对对象(Entry),根据键值对对象,来获取键和值
  • 根据Map集合来获取键值对对象,并放在Set集合当中

Set<Map.Entry<K,V> >entrySet()

  • 遍历set集合,获取每个键值对对象,,使用迭代器遍历,或者for-each遍历或者增强for循环
  • 得到键值对对象后,根据键值对对象再获取键和值

获取key:getKey();

获取value:getValue();

HashMap

HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,具有很快的访问速度,最多允许一条记录的键为 null,不支持线程同步。

HashMap 是无序的,即不会记录插入的顺序。

HashMap的初始容量是16

HashMap是线程不安全的

HashMap自动扩容时会扩大为原来的2倍,默认扩容因子为0.75,即达到最大容量的75%时开始扩容

Hashtable

Hashtable底层也是哈希表数据结构,是线程安全的,其中方法都带有synchronized关键字,效率较低

Hashtable的key值和value值不能为null,HashMap的key和value都可以为null

Hashtable的初始化容量是11,默认加载因子是0.75

Hashtable的扩容是原容量*2+1

LinkedHashMap

是Map接口的实现类,是HashMap的子类

和HashMap的不同之处是:可以记录元素存取的顺序,存取顺序一致

LinkedHashMap的底层是:哈希表+双向链表

LinkedHashMap也是线程不安全的

Collections工具类

该类中提供了多种操作集合的方法

将所有元素添加到指定集合当中

<T> static boolean addAll(Collection<? super T>c,T...elements

查找元素在指定集合中存在了几次

static int frequency(Collection c,Object o)

打乱集合元素的位置

static void shuffle(List<?> list)

不可变集合

不可变的List集合

List<String> list = List.of(E...element);

不可变的Set集合

Set集合中的值不能重复

Set<String> set = Set.of(E...element);

在不可变集合当中不能进行修改,删除,添加操作

不可变的Map集合

Map集合中的键不能重复

最多存储20个,10个键值对

Map<String,String> map = Map.of(K k1,Vv1);

存储超过10个键值对时,需要传入键值对对象

Map<Object,Object> map = Map.ofEntries(hm.entrySet().toArray(new Map.Entry[0]))

Map.copyof(hashMap)

  • 7
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
回答: Java集合框架是一组设计良好的接口和类,用于支持对一组对象进行操作。它包括了Collection、Set、List和Map等基本接口和类。Collection接口代表一组对象,每个对象都是它的子元素。Set是不包含重复元素的Collection,而List是有顺序的Collection,可以包含重复元素。Map是可以将键映射到值的对象,键不能重复。\[1\] 在Java集合框架中,有一些线程安全的类和接口,如Vector和Hashtable,它们是旧的,从Java一诞生就提供的,因此是线程安全的。而ArrayList和HashMap是在Java2时才提供的,它们是线程不安全的。因此,在使用这些类时需要注意线程安全的问题。\[2\] Java1.5引入了泛型,它允许我们为集合提供一个可以容纳的对象类型。这样,如果我们尝试添加其他类型的元素,编译时会报错,避免了在运行时出现ClassCastException的情况。泛型还使代码更整洁,不需要使用显式转换和instanceOf操作符。此外,泛型还带来了运行时的好处,因为它不会产生类型检查的字节码指令。\[3\] Iterator是Java集合框架中的一个接口,它用于遍历集合中的元素。它提供了一种统一的方式来访问集合中的元素,无论集合的具体实现是什么。Enumeration是Iterator的前身,它是在Java集合框架之前引入的。它们的主要区别在于Iterator支持删除操作,而Enumeration不支持。此外,Iterator还提供了更多的方法,如hasNext()和next(),使得遍历集合更加方便。\[3\] #### 引用[.reference_title] - *1* *2* [Java面试常问集合框架22道面试真题(详解)](https://blog.csdn.net/NObug_369/article/details/106099293)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [10道集合框架面试题(含解析),来看看你会多少](https://blog.csdn.net/weixin_62421895/article/details/126196672)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不是真的冷漠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值