【Java Se】集合框架

简介: 集合框架,在Java中使用时特别重要而且具有一定的难度(涉及到数据结构),后期做项目时也是常用到的一个工具.

前言


首先要说这个集合框架,在Java中使用时特别重要而且具有一定的难度(涉及到数据结构),后期做项目时也是常用到的一个工具,各位可以上点心。


初识集合框架


了解集合框架


通常,我们的程序在程序运行时才能知道创建多少个对象。在程序未运行时,程序开发阶段,我们根本不知道到底需要多少数量的对象,甚至不知道它的准确类型。为了满足这些常规的编程需要,我们要求能在任何时候,任何地点创建任意数量的对象,而这些对象用什么来容纳呢?我们首先想到了数组,但是数组只能放统一类型的数据,而且其长度是固定的,那怎么办呢?集合便应运而生了!


因为Java是面向对象的一门语言所以集合框架也需要被实例化为对象,Java集合类存放于 java.util 包中,是一个用来存放对象的容器。使用之前需要导入。


那我们在什么时候应该用集合框架呢?


1.无法预测存储数据的数量

2.同时存储具有一对一关系的数据 (Map)

3.需要进行数据的增删改查

4.数据重复问题


集合框架有以下几点需要注意:


1.集合框架只能存放对象。比如你存一个 int 型数据 1放入集合中,其实它是自动转换成 Integer 类后存入的,Java中每一种基本类型都有对应的引用类型。

2.集合框架存放的是多个对象的引用,对象本身还是放在堆内存中。

3.集合框架可以存放不同类型,不限数量的数据类型。


如果不知道包装类大家可以去看看 Java常用工具类之包装类与字符串


集合框架与数组

乍一看,集合与数组十分相似,但其实不然,我们接下来看一下集合与数组的区别

image.png

集合中储存的是对象的引用


可见集合与数组之间不同之处还是很明显的!


集合框架分类

集合整体框架图是非常的复杂的,我们先来看看一张来自网络的图:

image.png

这对我们初学者来说十分不友好,对于我们初学者第一次也没有必要了解的太深,下面由我来进行总结吧!


Java 集合框架主要包括两种容器类型,一种是集合(Collection),主要用来储存一类元素的集合。另一种是图(Map),用来存储键值对映射。Collection 接口又有主要有 3 种接口,List、Set 和 Queue,再下面是一些抽象类,最后是具体实现类,常用的有 ArrayList、LinkedList、HashSet、HashMap 等等。具体实现类不止这些但是我们先说这些当中最重要的几个。


集合框架实现顺序:

接口——>子接口——>抽象类(个别实现类才有)——>实现类


接口:是代表集合的抽象数据类型(未被实现)。例如 Collection、List、Set、Map 等。之所以定义多个接口,是为了以不同的方式(数据结构)操作集合对象


实现(类):是集合接口的具体实现。从本质上讲,它们是可重复使用的数据结构,例如:ArrayList、LinkedList、HashSet、HashMap


下面是它们的简单关系图:

image.png

下面就分别介绍一下吧!!!!


Collection

Collection 是最基本的集合接口,一个 Collection 代表一组 Object,即 Collection 的元素,

Java不提供直接继承自Collection的类,只提供继承于的子接口(如List和set)。即Collection几乎是所有集合的祖先接口(个人理解)。


Collection 接口存储一组不唯一,无序的对象。


下面是Collection常用的一些方法:

boolean add(E e)  
//添加元素 e 到集合中
void clear()  
//清除集合中的所有元素
boolean isEmpty() 
//判断集合是否是空集合
boolean remove(Object e)  
//如果元素 e 出现在集合中,删除其中一个
int size()  
//返回集合中的元素个数
Object[] toArray()  
//返回一个装有所有集合中元素的数组


不是说接口不能被实例化吗?那我们怎么使用Collection的方法呢?


当然一个接口是无法被实例化的,但是我们已经学习过多态了啊,我们可以创建一个父类的引用指向子类的实例化,这样就可以使用它自身的方法了。如:

//创建一个整型的顺序表
Collection collection = new ArrayList<>();
//使用Collection中的add方法给表中添加数据8
collection.add(8)


这里要注意因为集合中只能存放对象,不能存放基本数据类型,所以我们这里使用的是int的包装类Integer类型来声明的。


List

List接口是一个有序的 Collection,使用此接口能够精确的控制每个元素插入的位置,能够通过索引(元素在List中位置,类似于数组的下标)来访问List中的元素,第一个元素的索引为0,而且允许有相同的元素。


List 接口存储一组不唯一,有序(插入顺序)的对象。


List的常用方法:

//添加功能
boolean add(E e)
//向集合中添加一个元素(尾部)
void add(int index, E element)
//在指定位置添加元素
boolean addAll(Collection c)
//向集合中添加一个集合的元素,(只要继承于Collection的集合都可插入)
//删除功能
void clear()
//删除集合中的所有元素
E remove(int index)
//根据指定索引删除元素,并把删除的元素返回
boolean remove(Object o)
//从集合中删除指定的元素
boolean removeAll(Collection c)
//从集合中删除一个指定的集合元素。
//修改功能
E set(int index, E element)
//把指定索引位置的元素修改为指定的值,返回修改前的值。
//获取功能
E get(int index)
//获取指定位置的元素
Iterator iterator()
//就是用来获取集合中每一个元素。
//判断功能
boolean isEmpty()
//判断集合是否为空。
boolean contains(Object o)
//判断集合中是否存在指定的元素。
boolean containsAll(Collection c)
//判断集合中是否存在指定的一个集合中的元素。
//长度功能
int size()
//获取集合中的元素个数
//把集合转换成数组
Object[] toArray()


方法使用很简单,创建对象就可以直接引用了,与Collection类似,只不过增加了有序属性而已,就不演示了。。。


ArrayList

该类实现的是Collection接口的子接口List的接口,实现了可变大小的数组(动态),随机访问和遍历元素时,提供更好的性能。底层数据结构是数组,查询快,增删慢,线程不安全,效率高,可以存储重复元素。ArrayList 类位于 java.util 包中,使用前需要引入它。


ArrayList特点:


1.动态增长,以满足应用程序的需求

2.在列表尾部插入或删除非常有效

3.更适合查找和更新元素

4.ArrayList中的元素可以为null


ArrayList的构造方法:

ArrayList() 
//无参构造,这里没有指定顺序表容量,所以默认初始容量为10
ArrayList(Collection c) 
//利用其他 Collection 构建 ArrayList
ArrayList(int initialCapacity)  
//指定顺序表初始容量



这里的Collection c是只要继承于Collection的集合都可插入。

具体的Collection c的理解大家可以去传送门看看。


至于它的其他方法都是从接口过来的,就不需要说了,下面也是一样实现类的方法就不举例子说明了。


LinkedList

该类实现的是Collection接口的子接口List和Queue接口。Queue这个结构我们后面在讲,今天不具体说。主要用于创建链表数据结构,查找效率低。LinkedList 底层数据结构是链表,查询慢,增删快,线程不安全,效率高,可以存储重复元素。


1.与 ArrayList 一样,LinkedList 也按照索引位置排序,但它的元素之间是双向链接的

2.适合快速地插入和删除元素

3.LinkedList 实现 List 和 Queue 两个接口

4.LinkedList中允许有null(空)元素


LinkedList的构造方法:

LinkedList()  
//无参构造
LinkedList(Collection c)  
//利用其他 Collection 直接传入来构建 LinkedList


Set

Set 具有与 Collection 完全一样的接口,只是行为上不同,Set 不保存重复的元素。


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


Set与List都是继承于Collection的接口,那么Set与List有什么不同之处呢?总结如下:


Set 接口实例存储的是无序的,不重复的数据。List 接口实例存储的是有序的,可以重复的元素。

Set 检索效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。

List和数组类似,可以动态增长,根据实际存储的数据的长度自动增长List的长度。查找元素效率高,插入删除效率低,因为会引起其他元素位置改变。

可以看出来他们有各自的优缺点,当我们在选择时候应该根据他们特点来选择适合我们当前需求的一种结构。


Set的常用方法:

//添加功能
boolean add(E e);
boolean addAll(Collection c);
//删除功能
boolean remove(Object o);
boolean removeAll(Collection c);
void clear();
//长度功能
int size();
//判断功能
boolean isEmpty();
boolean contains(Object o);
boolean containsAll(Collection c);
boolean retainAll(Collection c); 
//获取Set集合的迭代器:
Iterator iterator();
//把集合转换成数组
Object[] toArray();
 T[] toArray(T[] a);
//判断元素是否重复,为子类提高重写方法
boolean equals(Object o);
int hashCode();


HashSet


该类实现的是Collection接口的子接口Set的接口,不允许出现重复元素,不保证集合中元素的顺序。HashSet底层数据结构采用哈希表实现,元素无序且唯一,线程不安全,效率高,可以存储null元素,元素的唯一性是靠所存储元素类型是否重写hashCode()和equals()方法来保证的,如果没有重写这两个方法,则无法保证元素的唯一性。


HashSet是Set的一个重要实现类,称为哈希集

HashSet中的元素无序并且不可以重复

HashSet中只允许一个null元素

具有良好的存取和查找性能

至于关于重写hashCode()和equals()方法,保证元素唯一性这个比较繁琐而且比较重要,今天先简单了解一下,后面我们会对它们的方法以及重要的东西在来说一遍的。


Map

Map 接口存储一组键值对象,提供key(键)到value(值)的映射,与python中字典类似。


一般来说Map的key是不容许重复的,如果key重复了也不会报错,但是同一个 key 所对应的值只有一个,就是最后你更新这个 key 的值。这样的话对我们的数据处理不友好,所以我们在一个Map里面的key一般都是独一无二的。


下面是图(Map)常用的一些方法:

V get(Object k) 
//根据指定的 k 查找对应的 v
V getOrDefault(Object k, V defaultValue)  
//根据指定的 k 查找对应的 v,没有找到就用默认值代替
V put(K key, V value) 
//将指定的 k-v 放入 Map
boolean containsKey(Object key)
//判断是否包含 key
boolean containsValue(Object value) 
//判断是否包含 value
Set> entrySet() 
//将所有的键值对返回
boolean isEmpty() 
//判断是否为空
int size()  
//返回键值对的数量
Map方法的使用与Collection也是类似的唯一不同之处就是声明类型的时候,需要声明两个类型,即:K—V。如下:
//创建一个对象
Map map = new HashMap<>();
//向map中添加数据
map.put("白白",888);



其他方法也是类似的,就不一一演示了。


HashMap

HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。该类实现了Map接口,根据键的HashCode值存储数据,具有很快的访问速度,最多允许一条记录的键为null,不支持线程同步。


1.基于哈希表的Map接口的实现

2.允许使用null值和null键

3.key值不允许重复

4.HashMap中的Entry对象是无序排列的

5.适用于Map中插入、删除和定位元素。


HashMap 的 key 与 value 类型可以相同也可以不同,可以是字符串(String)类型的 key 和 value,也可以是整型(Integer)的 key 和字符串(String)类型的 value。HashMap 类位于 java.util 包中,使用前需要引入它。


迭代器 Iterable

大家可能没有注意上面所有的集合类都实现了 Iterable 接口,那Iterable是什么玩意呢?


首先Java Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法


一般我们遍历一个集合可能用循环的方法实现,这是可以的,但是对于集合还有一种特殊的方法就是使用迭代器。迭代器是一个个具体对象,只不过它实现了 Iterator 接口和 ListIterator 接口。使用了迭代器,能够通过循环来得到或删除集合的元素。


其中Iterator 是 Java 迭代器最简单的实现,而ListIterator 是 Collection API 中的接口, 它扩展了 Iterator 接口,ListIterator 继承了 Iterator,以允许双向遍历列表和修改元素,是Iterable的进化版。


迭代器的基本操作是 next 、hasNext 和 remove:


调用 next() 会返回迭代器的下一个元素,并且更新迭代器的状态。


调用 hasNext() 用于检测集合中是否还有元素。


调用 remove() 将迭代器返回的元素删除。


具体使用如下:

//注意需要导入包在使用
import java.util.ArrayList;
import java.util.Iterator;
public class Text_5 {
    public static void main(String[] args){
        ArrayList  arrayList = new ArrayList();
        arrayList.add("白白牛!");
        arrayList.add("白白帅!");
        arrayList.add(1,"白白温柔!");
        //注意这里原来arrayList是什么类型的这个迭代器<>中也是同步的
        Iterator it = arrayList.iterator();
        while(it.hasNext()) {
            System.out.println(it.next());
        }
    }
}


输出为:

白白牛!

白白温柔!

白白帅!


这里需要注意顺序,是因为我arrayList.add(1,"白白温柔!");是指定位置加入的数据,所以白白温柔!在 白白帅!的前面。


其他方法用法也是类似的就不一一说明了。


相关文章
|
6天前
|
JSON Java Apache
非常实用的Http应用框架,杜绝Java Http 接口对接繁琐编程
UniHttp 是一个声明式的 HTTP 接口对接框架,帮助开发者快速对接第三方 HTTP 接口。通过 @HttpApi 注解定义接口,使用 @GetHttpInterface 和 @PostHttpInterface 等注解配置请求方法和参数。支持自定义代理逻辑、全局请求参数、错误处理和连接池配置,提高代码的内聚性和可读性。
|
15天前
|
人工智能 前端开发 Java
基于开源框架Spring AI Alibaba快速构建Java应用
本文旨在帮助开发者快速掌握并应用 Spring AI Alibaba,提升基于 Java 的大模型应用开发效率和安全性。
基于开源框架Spring AI Alibaba快速构建Java应用
|
15天前
|
消息中间件 Java 数据库连接
Java 反射最全详解 ,框架设计必掌握!
本文详细解析Java反射机制,包括反射的概念、用途、实现原理及应用场景。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
Java 反射最全详解 ,框架设计必掌握!
|
6天前
|
Java
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式。本文介绍了 Streams 的基本概念和使用方法,包括创建 Streams、中间操作和终端操作,并通过多个案例详细解析了过滤、映射、归并、排序、分组和并行处理等操作,帮助读者更好地理解和掌握这一重要特性。
14 2
|
6天前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
|
11天前
|
存储 Java
判断一个元素是否在 Java 中的 Set 集合中
【10月更文挑战第30天】使用`contains()`方法可以方便快捷地判断一个元素是否在Java中的`Set`集合中,但对于自定义对象,需要注意重写`equals()`方法以确保正确的判断结果,同时根据具体的性能需求选择合适的`Set`实现类。
|
11天前
|
存储 Java 开发者
在 Java 中,如何遍历一个 Set 集合?
【10月更文挑战第30天】开发者可以根据具体的需求和代码风格选择合适的遍历方式。增强for循环简洁直观,适用于大多数简单的遍历场景;迭代器则更加灵活,可在遍历过程中进行更多复杂的操作;而Lambda表达式和`forEach`方法则提供了一种更简洁的函数式编程风格的遍历方式。
|
11天前
|
Java 开发者
|
21天前
|
SQL Java 关系型数据库
java连接mysql查询数据(基础版,无框架)
【10月更文挑战第12天】该示例展示了如何使用Java通过JDBC连接MySQL数据库并查询数据。首先在项目中引入`mysql-connector-java`依赖,然后通过`JdbcUtil`类中的`main`方法实现数据库连接、执行SQL查询及结果处理,最后关闭相关资源。
|
18天前
|
缓存 Java 数据库连接
Hibernate:Java持久层框架的高效应用
通过上述步骤,可以在Java项目中高效应用Hibernate框架,实现对关系数据库的透明持久化管理。Hibernate提供的强大功能和灵活配置,使得开发者能够专注于业务逻辑的实现,而不必过多关注底层数据库操作。
12 1