Java——集合

一、简介

集合是 java 中提供的一种容器,可以用来存储多个对象数据。
既然有数组作为数据容器,Java为什么还提供集合容器?它们有啥区别呢?

  1. 数组的长度是固定的,不利于数据的增删。集合的长度是可变的。
  2. 数组中提供的属性和方法较少,不便于进行常用的增删改查操作,集合提供了更丰富的API。
  3. 数组存储数据的特点单一,即有序的,可重复的。集合有很多种类型,分别有不同的存储特点。

集合主要分为两大系列:Collection 和 Map,Collection 表示一组对象,Map表示一组映射关系或键值对。

请添加图片描述

二、Collection

Collection 表示一组对象。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。
所以JDK 不提供此接口的任何直接实现:它提供更具体的子接口(如 SetListQueue)实现。此接口通常用来传递 collection,并在需要最大普遍性的地方操作这些 collection。

Collection 常用方法

方法名称方法描述
add(E obj)添加元素对象到当前集合中
addAll(Collection<? extends E> other)添加other集合中的所有元素对象到当前集合中
boolean remove(Object obj)从当前集合中删除第一个找到的与obj对象equals返回true的元素。
boolean removeAll(Collection<?> coll)从当前集合中删除所有与coll集合中相同的元素。
void clear()清空集合
boolean isEmpty()判断当前集合是否为空集合
boolean contains(Object obj)判断当前集合中是否存在一个与obj对象equals返回true的元素。
boolean containsAll(Collection<?> c)判断c集合中的元素是否在当前集合中都存在。即c集合是否是当前集合的“子集”。
int size()获取当前集合中实际存储的元素个数
boolean retainAll(Collection<?> coll)当前集合仅保留与c集合中的元素相同的元素,即当前集合中仅保留两个集合的交集
Object[] toArray()返回包含当前集合中所有元素的数组

Iterator 迭代器

在程序开发中,经常需要遍历集合中的所有元素。针对这种需求,JDK专门提供了一个接口java.util.IteratorIterator接口也是Java集合中的一员,但它与CollectionMap接口有所不同,Collection接口与Map接口主要用于存储元素,而Iterator主要用于迭代访问(即遍历)Collection中的元素,因此Iterator对象也被称为迭代器。

常用方法:

方法名称方法描述
public E next()返回迭代的下一个元素
public boolean hasNext()如果仍有元素可以迭代,则返回 true
public void remove()通过迭代器删除元素

增强 for(foreach循环)

增强for循环(也称 foreach循环 )是JDK1.5以后出来的一个高级for循环,专门用来遍历数组和集合的。
通常只进行遍历元素,不要在遍历的过程中进行其他操作,否者会触发快速失败机制

Iterable 接口

实现这个接口允许对象成为 “foreach” 语句的目标。
Java 5时Collection接口继承了Iterable接口,因此Collection系列的集合就可以直接使用foreach循环遍历。
Iterable接口包含抽象方法public Iterator iterator(): 获取对应的迭代器。

foreach本质上就是使用Iterator迭代器进行遍历的

快速失败机制

当使用foreach或Iterator迭代器遍历集合时,同时调用迭代器自身以外的方法修改了集合的结构,例如调用集合的add和remove方法时,就会 ConcurrentModificationException

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class TestForeach {
	public static void main(String[] args) {
		Collection<String> list = new ArrayList<>();
		list.add("hello");
		list.add("java");
		list.add("world");
		
		Iterator<String> iterator = list.iterator();
		while(iterator.hasNext()){
			list.remove(iterator.next());
		}
	}
}

这样设计是因为,迭代器代表集合中某个元素的位置,内部会存储某些能够代表该位置的信息。当集合发生改变时,该信息的含义可能会发生变化,这时操作迭代器就可能会造成不可预料的事情。因此,果断抛异常阻止,是最好的方法。这就是Iterator迭代器的快速失败(fail-fast)机制

三、List

java.util.List接口继承自Collection接口,是单列集合的一个重要分支。除了从Collection集合继承的方法外,List 集合里添加了一些根据索引来操作集合元素的方法。
List 集合类中元素 有序、且可重复

List 集合的方法

List 集合特有的方法都是跟索引相关

方法名称方法描述
void add(int index, E ele)添加元素
boolean addAll(int index, Collection<? extends E> eles)添加元素
E get(int index)获取元素
List subList(int fromIndex, int toIndex)获取元素
int indexOf(Object obj)获取元素索引
int lastIndexOf(Object obj)获取元素索引
E remove(int index)删除和替换元素
E set(int index, E ele)删除和替换元素

一、 ArrayList

ArrayList是 List 接口的典型实现类,底层使用长度可变的数组实现,常用方法都来自Collection和List接口。
ArrayList因为底层使用了数组存储数据,所以具有 查询快,增、删慢 的特点。

二、LinkedList

LinkedList 是List接口的另一个常用实现类。
LinkedList 底层存储数据使用链表结构(双向链表),特点:增删快,查询慢。
LinkedList 也实现了Deque接口(双端队列),此接口提供了实现队列和栈结构的方法。

1. 常用方法(首、尾元素的操作,效率高):

  • void addFirst(Object obj )
  • void addLast(Object obj )
  • Object getFirst()
  • Object getLast()
  • Object removeFirst()
  • Object removeLast ()

三、ListIterator

List 集合额外提供了一个 listIterator() 方法,该方法返回一个 ListIterator 对象, ListIterator 接口继承了 Iterator 接口,提供了专门操作 List 的方法:

  • void add():通过迭代器添加元素到对应集合
  • void set(Object obj):通过迭代器替换正迭代的元素
  • void remove():通过迭代器删除刚迭代的元素
  • boolean hasPrevious():如果以逆向遍历列表,往前是否还有元素。
  • Object previous():返回列表中的前一个元素。
  • int previousIndex():返回列表中的前一个元素的索引
  • boolean hasNext()
  • Object next()
  • int nextIndex()

四、Set 集合

Set接口是Collection的子接口,Set 集合不允许包含相同的元素,即元素唯一
Set的常用实现类有:HashSet、TreeSet、LinkedHashSet。

一、HashSet

HashSet 是 Set 接口的典型实现,大多数时候使用 Set 集合时都使用这个实现类。
java.util.HashSet底层的实现其实是一个java.util.HashMap支持,然后HashMap的底层物理实现是一个Hash表
HashSet 按 Hash 算法来存储集合中的元素,因此具有很好的存取和查找性能。
在这里插入图片描述

1. HashSet 集合判断两个元素相等的标准
1.两个对象通过 hashCode() 方法比较相等
2.并且两个对象的 equals() 方法返回值也相等。
因此,存储到HashSet的元素要重写hashCode和equals方法。

2. 为什么重写hashCode方法
提高哈希性能。
如何重写hashCode方法, 提高哈希性能
内容相同的元素哈希值一定相同
内容不同的元素哈希值尽量不同
哈希值相同不一定是相同的元素
可以使用IDEA模板重写hashCode和equals方法

二、LinkedHashSet

LinkedHashSet是HashSet的子类,它在HashSet的基础上,在结点中增加两个属性before和after维护了结点的前后添加顺序。java.util.LinkedHashSet,它是链表和哈希表组合的一个数据存储结构。LinkedHashSet插入性能略低于 HashSet,但在迭代访问 Set 里的全部元素时有很好的性能。

在这里插入图片描述

三、 TreeSet

元素唯一,无序(存取顺序), 但是实现了排序(大小排序)
底层结构:里面维护了一个TreeMap,都是基于红黑树实现的。
红黑树是一种相对平衡的二叉树,查询效率高于链表。(平衡二叉树追求绝对平衡,左右子树差值不能超过1)
实现了元素的排序,即TreeSet会对元素进行大小比较
要求:
元素类型必须实现Comparable接口
创建集合是通过构造器传入一个外部比较器 Comparator

二叉树的遍历方式有:

  • 前序遍历:中-左-右
  • 中序遍历:左-中-右
  • 后序遍历:左-右-中

在这里插入图片描述

五、Map

现实生活中,我们常会看到这样的一种集合:IP地址与主机名,身份证号与个人等,这种一一对应的关系,就叫做映射。Java提供了专门的集合类用来存放这种对象关系的对象,即java.util.Map<K,V>接口。

  • Collection中的集合称为单列集合,Map中的集合称为双列集合。

一、Map 常用方法

方法名称方法描述
V put(K key,V value)添加操作
void putAll(Map<? extends K,? extends V> m)添加操作
void clear()删除
V remove(Object key)删除
V get(Object key)元素查询的操作
boolean containsKey(Object key)元素查询的操作
boolean containsValue(Object value)元素查询的操作
boolean isEmpty()判断元素是否为空
Set keySet()返回 key 的集合
Collection values()返回 value 的集合
Set<Map.Entry<K,V>> entrySet()返回 key, 和value, 封装到 entry 中
int size()返回集合的长度

二、Map 集合的遍历

Map的遍历,不能支持foreach,因为Map接口没有继承java.lang.Iterable接口,也没有实现Iterator iterator()方法。只能用如下方式遍历:

(1)分开遍历:

  • 单独遍历所有key
  • 单独遍历所有value

(2)成对遍历:

  • 遍历的是映射关系Map.Entry类型的对象,Map.Entry是Map接口的内部接口。每一种Map内部有自己的Map.Entry的实现类。在Map中存储数据,实际上是将Key---->value的数据存储在Map.Entry接口的实例中.

三、Map实现类

Map接口的常用实现类
其中HashMap是 Map 接口使用频率最高的实现类。

HashMap
Hashtable
TreeMap
LinkedHashMap
Properties

HashMap

HashMap 使用 哈希表保存数据
判断两个 key 相等的标准是:两个 key 的hashCode 值相等,并且 equals() 方法也返回 true。因此,为了成功地在哈希表中存储和获取对象,用作键的对象必须实现 hashCode 方法和 equals 方法。

  • HashMap是线程不安全的,并允许使用 null 值和 null 键。、

在这里插入图片描述

HashMap构造方法:

  • ​ HashMap();
  • ​ HashMap(int initialCapacity);//指定初始化容量

Hahtable

和HashMap基本上一样,不常用

  • Hashtable是线程安全的,任何非 null 对象都可以用作键或值。

LinkedHashMap

LinkedHashMap 是 HashMap 的子类。
特点: 元素唯一,有序
底层结构:哈希表基础上又维护了一个链表,用于保证元素的迭代顺序。
效率:略低于HashMap

TreeMap

特点:元素唯一,无序, 但实现了排序(大小排序)
底层机构:红黑树,一种相对平衡的二叉树
效率:查询效率高于链表。
该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法。

Properties

Properties 类是 Hashtable 的子类。
特点:key和value都是字符串
特有方法
setProperty(String key,String value)
getProperty(String key)

六、总结

Collection:集合根接口,存储一组对象。

  • List:Collection的子接口。数据可重复,有序的,通过索引访问元素。
    • ArrayList:
      存储结构:数组存储
      特点:查询效率高, 增删慢
    • LinkedList:
      存储结构:双向链表
      特点:查询效率低, 但是插入和删除效率高
    • Vector:
      等同于 Arraylist实现,线程安全的,效率较低
  • Set:Collection的子接口,数据不可重复,通常无序,不能通过索引访问。
    • HashSet:
      存储结构:底层是HashMap
      特点: 综合效率较高。
    • LinkedHashSet: 底层是 LinkedHashMap
      存储结构: 哈希表基础维护了一个链表, 用来保证数据有序
      特点: 效率没有HashSet高, 有序数据
    • TreeSet:
      存储机构:使用红黑树存储
      特点:因为红黑树的原因, 数据是自动排序好的。

Map: 双列集合,存储的是Key, value

  • HashMap:
    存储结构:JDK1.7 数组 + 链表 JDK1.8 数组 + 链表 + 红黑树
    特点:线程不安全,允许 key, value为 null
  • Hashtable:
    存储结构: 等同于 HashMap
    特点: 线程安全, key, value都不能为 null
  • LinkedHashMap:
    存储结构:HashMap之上维护了链表
    特点: 按照插入顺序存储
  • TreeMap:
    可对键排序
  • Properties
    存储结构
    特点: 只能存储Stirng 类型的 数据。

Collections工具类

Collections 是一个操作 Set、List 和 Map 等集合的工具类。Collections 中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作,还提供了对集合对象设置不可变、对集合对象实现同步控制等方法:

方法名称方法描述
public static boolean addAll(Collection<? super T> c,T… elements)将所有指定元素添加到指定 collection 中。
public static int binarySearch(List<? extends Comparable<? super T>> list,T key)在List集合中查找某个元素的下标,但是List的元素必须是T或T的子类对象,而且必须是可比较大小的,即支持自然排序的。而且集合也事先必须是有序的,否则结果不确定。
public static int binarySearch(List<? extends T> list,T key,Comparator<? super T> c)在List集合中查找某个元素的下标,但是List的元素必须是T或T的子类对象,而且集合也事先必须是按照c比较器规则进行排序过的,否则结果不确定。
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)在coll集合中找出最大的元素,集合中的对象必须是T或T的子类对象,而且支持自然排序
public static T max(Collection<? extends T> coll,Comparator<? super T> comp)在coll集合中找出最大的元素,集合中的对象必须是T或T的子类对象,按照比较器comp找出最大者
public static void reverse(List<?> list)反转指定列表List中元素的顺序。
public static void shuffle(List<?> list)List 集合元素进行随机排序,类似洗牌
public static <T extends Comparable<? super T>> void sort(List list)根据元素的自然顺序对指定 List 集合元素按升序排序
public static void sort(List list,Comparator<? super T> c)根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
public static void swap(List<?> list,int i,int j)将指定 list 集合中的 i 处元素和 j 处元素进行交换
public static int frequency(Collection<?> c,Object o)返回指定集合中指定元素的出现次数
public static void copy(List<? super T> dest,List<? extends T>src)将src中的内容复制到dest中
public static boolean replaceAll(List list,T oldVal,T newVal)使用新值替换 List 对象的所有旧值
  • Collections 类中提供了多个 synchronizedXxx() 方法,该方法可使将指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题
  • Collections类中提供了多个unmodifiableXxx()方法,该方法返回指定 Xxx的不可修改的视图。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值