集合概述

集合框架体系,Collection接口,Map接口,Collections工具类

Author: Msuenb

Date: 2023-02-17


集合是 Java 中提供的一种容器,可以用来存储多个数据。

数组也是容器,但相较于集合,数组有些不足之处:

  • 数组的长度是固定的。集合的长度是可变的。
  • 数组保存的必须是同一类型(或兼容) 的元素
  • 数组的添加和删除元素操作比较麻烦

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

Collection 和 Map 集合体系如下图:

Collection接口

Collection 表示一组对象,这些对象也称为 collection 的元素。

  • 一些 collection 允许有重复的元素,而另一些则不允许;一些 collection 是有序的,而另一些则是无序的。
  • JDK 不提供此接口的任何直接实现,而是提供更具体的子接口(如 Set 和 List、Queue)实现。

Collection常用API

Collection 是所有单列集合的父接口,在 Collection 中定义了单列集合(List、Set)通用的一些方法,这些方法可用于操作所有的单列集合。常用方法如下:

  1. add(E obj):添加单个元素
  2. addAll(Collection<? extends E> other):添加多个元素
  3. boolean remove(Object obj) :删除指定元素
  4. boolean removeAll(Collection<?> coll):删除多个元素
  5. boolean isEmpty():判断当前集合是否为空集合。
  6. boolean contains(Object obj):判断指定元素是否存在
  7. boolean containsAll(Collection<?> c):判断多个元素是否都存在
  8. int size():获取当前集合中实际存储的元素个数
  9. void clear():清空集合

由于 Collection 没有任何直接实现类,这里以 ArrayList 实现类演示

public class CollectionAPITest {
    public static void main(String[] args) {
        Collection coll = new ArrayList();

        // 添加单个元素
        coll.add("jack");
        coll.add(10);   // 相当于 coll.add(new Integer(10))
        coll.add(true);
        System.out.println(coll);

        // 添加多个元素
        Collection c = new ArrayList();
        c.add("tom");
        c.add("jerry");
        coll.addAll(c);
        System.out.println(coll);

        // 判断是否包含指定元素
        boolean b = coll.contains("tom");
        System.out.println(b);

        // 判断是否包含多个元素
        boolean b1 = coll.containsAll(c);
        System.out.println(b1);

        // 获取当前集合元素个数
        int size = coll.size();
        System.out.println(size);

        // 删除指定元素
        coll.remove("tom");
        System.out.println(coll);

        // 删除多个元素
        coll.removeAll(c);
        System.out.println(coll);

        // 清空集合
        coll.clear();

        // 判断集合是否为空集合
        System.out.println(coll.isEmpty());
    }
}

Iterator迭代器

Iterator 接口也是 Java 集合中的一员,但它与Collection、Map接口有所不同,Collection接口与Map接口主要用于存储元素,而 Iterator 主要用于迭代访问(遍历) Collection 中的元素,因此 Iterator 对象也被称为迭代器。

遍历 Collection 集合,需要获取该集合迭代器,然后完成迭代操作:

  • public Iterator iterator():获取集合对应的迭代器,用来遍历集合中的元素的。

  • public boolean hasNext():判断是否有下一个元素可以迭代,有则返回 true。

  • public E next():返回迭代的下一个元素。

Iterator 迭代集合中元素演示:

public class IteratorTest {
    public static void main(String[] args) {
        Collection coll = new ArrayList();
        coll.add("tom");
        coll.add("jerry");
        coll.add("smith");

        Iterator iterator = coll.iterator();	// 获取迭代器对象
        while(iterator.hasNext()) {	// 判断是否还有元素可迭代
            System.out.println(iterator.next());	// 取出下一个元素
        }
    }
}

增强for循环

java.lang.Iterable 接口还提供了一个forEach默认方法,用于完成集合元素的迭代。 Collection 接口继承了 java.lang.Iterable 接口,因此Collection系列的集合就可以直接使用 foreach 循环遍历。

foreach 循环的语法格式:

for(元素类型 元素名 : 集合名){
}
//这里元素名就是一个临时变量,自己命名就可以

使用演示:

Collection coll = new ArrayList();
coll.add("tom");
coll.add("jerry");
coll.add("smith");

for (Object o : coll) {
    System.out.println(o);
}

对于集合类型来说,foreach 循环其实就是使用 Iterator 迭代器来完成元素的遍历的。

Java中的数组也支持这种语法糖。只不过编译器在处理 foreach 遍历数组时,是转换为普通for循环的。

List接口

java.util.List接口继承自 Collection 接口,是单列集合的一个重要分支,习惯将实现了 List 接口的对象称为List集合。

List的常用实现类有:ArrayList、Vector、LinkedList、Stack等。

List接口特点:

  • List集合所有的元素是以一种线性方式进行存储的
  • 它是一个元素存取有序的集合。即元素的存入顺序和取出顺序有保证。
  • 它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是一个道理)。
  • 集合中可以有重复的元素

List 作为 Collection 集合的子接口,不但继承了 Collection 接口中的全部方法,而且还增加了一些根据元素索引来操作集合的特有方法,如下:

  1. void add(int index, E ele):把元素添加到指定位置
  2. boolean addAll(int index, Collection<? extends E> eles):把一组元素添加到指定位置
  3. E remove(int index):删除指定位置的元素
  4. E set(int index, E ele):替换 [index] 位置的元素
  5. E get(int index):返回[index]位置的元素
  6. List subList(int fromIndex, int toIndex):返回[fromIndex, toIndex)范围的元素
  7. int indexOf(Object obj):查询obj在列表中的位置,如果有重复,返回第1个
  8. int lastIndexOf(Object obj):查询obj在列表中的位置,如果有重复,返回最后1个

示例代码:

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

public class ListAPITest {
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("hello");
        list.add("java");
        list.add("world");
        list.add("mysql");
        list.add("java");

        // 添加元素到指定位置
        list.add(2, "tom");
        System.out.println(list);

        // 添加一组元素到指定位置
        List list1 = new ArrayList();
        list.add("jerry");
        list.add("smith");
        list.addAll(3, list1);
        System.out.println(list);

        // 替换指定位置元素
        list.set(2, "zhangsan");
        System.out.println(list);

        // 返回指定位置的元素
        Object o = list.get(2);
        System.out.println(o);

        // 删除指定位置元素
        list.remove(2);
        System.out.println(list);

        // 返回指定范围[from, to)的元素
        List list2 = list.subList(5, 7);
        System.out.println(list2);

        // 查询元素首次出现的位置
        int java = list.indexOf("java");
        System.out.println(java);

        // 查询元素最后一次出现的位置
        int java1 = list.lastIndexOf("java");
        System.out.println(java1);
    }
}

Set接口

Set 接口是 Collection 的子接口,Set 接口没有提供额外的方法。

  • Set 集合不允许包含相同的元素,即元素不可重复。

  • Set 集合支持的遍历方式和 Collection 集合一样:foreach 和 Iterator。

  • Set 的常用实现类有:HashSet、TreeSet、LinkedHashSet 等。

import java.util.HashSet;

public class TestSet {
    public static void main(String[] args){
        HashSet set = new HashSet();
        set.add("hello");
        set.add("java");
        set.add("hello");	// 添加不成功
        System.out.println(set);
    }
}
  • HashSet 和 LinkedHashSet 元素不可重复是依赖于 equals 和 hashCode 方法

  • TreeSet 元素不可重复是依赖于元素大小关系的。

    • 要么元素类型实现 Comparable 接口,重写 compareTo 方法,

    • 要么创建 TreeSet 时,指定 Comparator 接口实现类对象,重写 compare 方法

Map

像IP地址与主机名,身份证号与个人等,这种一一对应的关系,就叫做映射。Java提供了专门的集合类用来存放这种对象关系的对象,即java.util.Map<K,V>接口。

Map 接口下的集合与 Collection 接口下的集合,它们存储数据的形式不同。

  • Collection 中的集合,元素是孤立存在的,向集合中存储元素采用一个个元素的方式存储。
  • Map 中的集合,元素是成对存在的。每个元素由键与值两部分组成,通过键可以找对所对应的值。
  • Collection 中的集合称为单列集合,Map 中的集合称为双列集合。
  • 需要注意的是,Map中的集合不能包含重复的键,值可以重复;每个键只能对应一个值。

Map常用方法:

  1. V put(K key,V value):添加一对键值对

  2. void putAll(Map<? extends K,? extends V> m):添加一组键值对

  3. void clear():清空map

  4. V remove(Object key):根据key删除一对键值对

  5. default V replace(K key, V value):找到目标key,替换value

  6. V get(Object key):根据key返回value

  7. boolean containsKey(Object key):判断key是否存在

  8. boolean containsValue(Object value):判断value是否存在

  9. boolean isEmpty():判断map是否为空

  10. int size():获取键值对的数量

public class MapAPITest {
    public static void main(String[] args) {
        //创建 map对象
        HashMap<String, String> map = new HashMap<String, String>();

        //添加元素到集合
        map.put("黄晓明", "杨颖");
        map.put("文章", "马伊琍");
        map.put("文章", "姚笛");
        map.put("邓超", "孙俪");
        System.out.println(map.size());
        System.out.println(map);

        //删除键值对
        map.remove("文章");
        System.out.println(map);

        //修改value
        map.replace("文章","马伊琍");
        System.out.println(map);

        // 替换指定 key 对应的value
        map.replace("黄晓明", "angelababy");
        System.out.println(map);

        // 查看key 对应的value
        System.out.println(map.get("黄晓明"));
    }
}

注意:Map<K,V>中,key可以为null,但只能有一个;value也可以为null,可以有多个。

map.put(null, "jerry");
map.put(null, null);    // key重复 替换value
map.put("cat", null);   // value 可以重复

Map集合遍历

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

  1. 分开遍历:

    • 单独遍历所有key:Set keySet()

    • 单独遍历所有value:Collection values()

  2. 成对遍历:

    • 遍历所有键值对:Set<Map.Entry<K,V>> entrySet()

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

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class MapIterateTest {
    public static void main(String[] args) {
        Map map = new HashMap();
        map.put("许仙", "白娘子");
        map.put("董永", "七仙女");
        map.put("牛郎", "织女");
        map.put("许仙", "小青");

        System.out.println("所有的key: ");
        Set set = map.keySet();
        for (Object o : set) {
            System.out.print(o + " ");
        }

        System.out.println("所有的value: ");
        Collection values = map.values();
        for (Object value : values) {
            System.out.print(value + " ");
        }

        System.out.println("所有的映射关系: ");
        Set entrySet = map.entrySet();
        for (Object entry : entrySet) {
            System.out.println(entry);
        }
    }
}

Collections工具类

参考操作数组的工具类:Arrays。

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的不可修改的视图。
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class CollectionsTest {
    @Test
    public void test01() {
        // addAll
        Collection coll = new ArrayList();
        Collections.addAll(coll, "hello", "java");
        Collections.addAll(coll, 1, 2, 3);
        System.out.println(coll);
    }

    @Test
    public void test02() {

        List list = new ArrayList();
        Collections.addAll(list, "hello","world","java","php", "hello");

        Collections.sort(list); // String 实现了Comparable接口
        System.out.println(list);
		// 反转
        Collections.reverse(list); 
        System.out.println(list);
        // 重洗
        Collections.shuffle(list);
        System.out.println(list);
        // 交换
        Collections.swap(list, 1, 2);
        System.out.println(list);
        // 指定元素出现次数
        int hello = Collections.frequency(list, "hello");
        System.out.println(hello);
    }

    @Test
    public void test03() {
        // 复制元素
        List<Integer> list = new ArrayList<>();
        for(int i=1; i<=5; i++){//1-5
            list.add(i);
        }

        List<Integer> list2 = new ArrayList<>();
        for(int i=11; i<=13; i++){//11-13
            list2.add(i);
        }

        Collections.copy(list, list2);
        System.out.println(list);
    }

    @Test
    public void test4(){
        List<String> list = new ArrayList<>();
        Collections.addAll(list,"hello","java","world","hello","hello");

        Collections.replaceAll(list, "hello","chai");
        System.out.println(list);
    }
}
posted @ 2023-02-17 21:15  msuenb  阅读(22)  评论(0编辑  收藏  举报