Java中的集合(上)

第11章 集合

本章学习目标

  • 知道集合与数组的区别
  • 掌握Collection接口的常用方法
  • 理解HashSet、LinkedHashSet、TreeSet的区别
  • 理解Set与List集合的区别
  • 掌握List接口的常用方法
  • 理解Vector和ArrayList的区别
  • 理解ArrayList与LinkedList的区别
  • 掌握Queue和Deque队列接口的常用方法
  • 掌握栈和队列的区别
  • 知道Collection集合与Map集合的区别
  • 掌握Map接口的常用方法
  • 掌握Hashtable与HashMap的区别
  • 掌握LinkedHashMap、TreeMap、Properties的区别
  • 了解Set与Map之间的关系
  • 掌握集合工具类Collections的常用方法
  • 掌握数组与List集合之间的转换
  • 掌握集合框架关系图

11.1 Collection集合

11.1.1 集合的概念

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

集合和数组既然都是容器,它们有啥区别呢?

  • 数组的长度是固定的。集合的长度是可变的。
  • 数组中可以存储基本数据类型值,也可以存储对象,而集合中只能存储对象

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

11.1.2 Collection<E>接口

Collection 层次结构中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。JDK 不提供此接口的任何直接实现:它提供更具体的子接口(如 Set 和 List、Queue)实现。此接口通常用来传递 collection,并在需要最大普遍性的地方操作这些 collection。

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

1、添加元素

  • (1)add(E obj):添加元素对象到当前集合中
  • (2)addAll(Collection<? extends E> other):添加other集合中的所有元素对象到当前集合中,即this = this ∪ other

2、删除元素

  • (1) boolean remove(Object obj) :从当前集合中删除第一个找到的与obj对象equals返回true的元素。
  • (2)boolean removeAll(Collection<?> coll):从当前集合中删除所有与coll集合中相同的元素。即this = this - this ∩ coll
  • (3)boolean retainAll(Collection<?> coll):从当前集合中删除两个集合中不同的元素,使得当前集合仅保留与c集合中的元素相同的元素,即当前集合中仅保留两个集合的交集,即this = this ∩ coll;
  • (4)void clear():清空集合
  • (5)boolean removeIf(Predicate<? super E> filter) :删除满足给定条件的此集合的所有元素。removeIf方法是**Java8**引入的。

3、查询与获取元素

  • (1)boolean isEmpty():判断当前集合是否为空集合。
  • (2)boolean contains(Object obj):判断当前集合中是否存在一个与obj对象equals返回true的元素。
  • (3)boolean containsAll(Collection<?> c):判断c集合中的元素是否在当前集合中都存在。即c集合是否是当前集合的“子集”。
  • (4)int size():获取当前集合中实际存储的元素个数
  • (5)Object[] toArray():返回包含当前集合中所有元素的数组
  • (6)T[] toArray(T[] arr):返回包含当前集合中所有元素的数组

4、遍历集合

  • (1)default void forEach(Consumer<? super T> action)
  • (2)foreach循环。

所有实现了java.lang.Iterable接口的集合都支持foreach循环。而Collection接口就继承了Iterable接口。

5、示例代码

package com.atguigu.collection;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.function.Predicate;

public class TestCollection {
    @Test
    public void test1(){
        Collection<String> coll = new ArrayList<>();
        coll.add("hello");
        coll.add("java");
        coll.add("world");
        System.out.println(coll);
    }

    @Test
    public void test2(){
        Collection<String> coll = new ArrayList<>();
        coll.add("hello");
        coll.add("java");
        coll.add("world");
        System.out.println(coll);

        Collection<String> other = new ArrayList<>();
        other.add("尚硅谷");
        other.add("JavaEE");
        other.add("大数据");
        other.add("嵌入式");
        other.add("鸿蒙");

        coll.addAll(other);
        System.out.println(coll);
    }

    @Test
    public void test3(){
        Collection<String> coll = new ArrayList<>();
        coll.add("hello");
        coll.add("java");
        coll.add("world");
        coll.add("atguigu");
        coll.add("chai");

        coll.remove("java");
        System.out.println(coll);

        Predicate<String> p = new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.contains("a");
            }
        };
        coll.removeIf(p);
        System.out.println(coll);

        Collection<String> other = new ArrayList<>();
        other.add("尚硅谷");
        other.add("JavaEE");
        other.add("world");
        other.add("hello");
        coll.removeAll(other);

        System.out.println(coll);
    }

    @Test
    public void test4() {
        Collection<String> coll = new ArrayList<>();
        coll.add("hello");
        coll.add("java");
        coll.add("world");
        coll.add("atguigu");
        coll.add("chai");

        Collection<String> other = new ArrayList<>();
        other.add("尚硅谷");
        other.add("JavaEE");
        other.add("world");
        other.add("hello");
        coll.retainAll(other);
        System.out.println(coll);
    }


    @Test
    public void test5() {
        Collection<String> coll = new ArrayList<>();
        coll.add("hello");
        coll.add("java");
        coll.add("world");
        coll.add("atguigu");
        coll.add("chai");

        System.out.println(coll.isEmpty());
        System.out.println(coll.size());
        System.out.println(coll.contains("java"));

        Collection<String> other = new ArrayList<>();
        other.add("尚硅谷");
        other.add("JavaEE");
        other.add("world");
        other.add("hello");
        System.out.println(coll.containsAll(other));
    }

    @Test
    public void test6() {
        Collection<String> coll = new ArrayList<>();
        coll.add("hello");
        coll.add("java");
        coll.add("world");
        coll.add("atguigu");
        coll.add("chai");

        Object[] objects = coll.toArray();
        System.out.println(Arrays.toString(objects));
        
        String[] strings = new String[0];
        strings = coll.toArray(strings);
        System.out.println(Arrays.toString(strings));
    }
    
    @Test
    public void test7() {
        Collection<String> coll = new ArrayList<>();
        coll.add("hello");
        coll.add("java");
        coll.add("world");
        coll.add("atguigu");
        coll.add("chai");

        Consumer<String> c = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        coll.forEach(c);
    }
    
    @Test
    public void test8() {
        Collection<String> coll = new ArrayList<>();
        coll.add("hello");
        coll.add("java");
        coll.add("world");
        coll.add("atguigu");
        coll.add("chai");

        for (String s : coll) {
            System.out.println(s);
        }
    }
}

11.2 Set集合

11.2.1 Set接口介绍

`Set`接口是`Collection`的子接口,set接口没有提供额外需要实现类实现的抽象方法。但是比`Collection`接口更加严格了。

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

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

package com.atguigu.list;

import org.junit.Test;

import java.util.HashSet;

public class TestSet {
    @Test
    public void test03(){
        LinkedHashSet<String> set = new LinkedHashSet<>();//按照添加顺序,不可重复
        set.add("hello");
        set.add("java");
        set.add("hello");
        set.add("java");
        System.out.println(set);
    }
    @Test
    public void test02(){
        TreeSet<String> set = new TreeSet<>();//有大小顺序,不可重复
        set.add("hello");
        set.add("java");
        set.add("hello");
        set.add("java");
        System.out.println(set);
    }
    
    @Test
    public void test01(){
        HashSet<String> set = new HashSet<>();//无序,不可重复
        set.add("hello");
        set.add("java");
        set.add("hello");
        set.add("java");
        System.out.println(set);
    }
}

11.2.2 元素相等和重复问题

  1. HashSet和LinkedHashSet元素不可重复是依赖于equals和hashCode方法
package com.atguigu.set;

public class Circle {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    public double getRadius() {
        return radius;
    }

    public void setRadius(double radius) {
        this.radius = radius;
    }

    @Override
    public String toString() {
        return "Circle{" +
                "radius=" + radius +
                '"}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass()!= o.getClass()) return false;

        Circle circle = (Circle) o;

        return Double.compare(circle.radius, radius) == 0;
    }

    @Override
    public int hashCode() {
        long temp = Double.doubleToLongBits(radius);
        return (int) (temp ^ (temp >>> 32));
    }
}
 @Test
    public void test08(){
        HashSet<Circle> set = new HashSet<>();
        set.add(new Circle(1));
        set.add(new Circle(1));
        System.out.println(set);
    }
  1. TreeSet元素不可重复是依赖于比较器的compareTo或compare方法
package com.atguigu.set;

import org.junit.Test;

import java.text.Collator;
import java.util.Comparator;
import java.util.Locale;
import java.util.TreeSet;

public class TestTreeSet {
    @Test
    public void test1(){
        //String类实现Comparable,所以String类的对象可以方法TreeSet中,默认按照字符的编码值排序
        TreeSet treeSet = new TreeSet();
        treeSet.add("hello");
        treeSet.add("java");
        treeSet.add("haha");
        treeSet.add("world");
        treeSet.add("heihei");
        System.out.println(treeSet);
        //[haha, heihei, hello, java, world]
    }

    @Test
    public void test2(){
        //使用String类的定制比较器,按照中文的拼音顺序
        Collator collator = Collator.getInstance(Locale.CHINA);//得到一个实现了Comparator接口的字符串定制比较器
        TreeSet treeSet = new TreeSet(collator);
        treeSet.add("张三");
        treeSet.add("李四");
        treeSet.add("王五");
        treeSet.add("赵六");
        System.out.println(treeSet);
        //[李四, 王五, 张三, 赵六]
        //li   wang  zhang  zhao
    }

    @Test
    public void test3(){
        //使用String类的定制比较器,按照字符串的长短
        Comparator lengthComparator = new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                String s1 = (String) o1;
                String s2 = (String) o2;
                return s1.length() - s2.length();
            }
        };
        TreeSet treeSet = new TreeSet(lengthComparator);
        treeSet.add("hi");
        treeSet.add("hello");
        treeSet.add("hey");
        treeSet.add("haha");
        treeSet.add("heihei");
        treeSet.add("world");//没添加成功  因为world和hello一样长
        treeSet.add("java");//没添加成功   因为java和haha一样长
        System.out.println(treeSet);
        //[hi, hey, haha, hello, heihei]

    }

    @Test
    public void test4(){
        //使用String类的定制比较器,按照字符串的长短,长度一样,再按内容比较大小
        Comparator lengthComparator = new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                String s1 = (String) o1;
                String s2 = (String) o2;
                int result = s1.length() - s2.length();
                if(result == 0){
                    return s1.compareTo(s2);
                }
                return result;
            }
        };
        TreeSet treeSet = new TreeSet(lengthComparator);
        treeSet.add("hi");
        treeSet.add("hello");
        treeSet.add("hey");
        treeSet.add("haha");
        treeSet.add("heihei");
        treeSet.add("world");
        treeSet.add("java");
        System.out.println(treeSet);
        //[hi, hey, haha, java, hello, world, heihei]

    }
}

11.3 List集合

11.3.1 `List<E>`接口介绍

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

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

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

这就像银行门口客服,给每一个来办理业务的客户分配序号:第一个来的是“张三”,客服给他分配的是0;第二个来的是“李四”,客服给他分配的1;以此类推,最后一个序号应该是“总人数-1”。

1563549818689.png

注意:

List集合关心元素是否有序,而不关心是否重复,请大家记住这个原则。例如“张三”可以领取两个号。

在JavaSE中`List`名称的类型有两个,一个是`java.util.List<E>`集合接口,一个是`java.awt.List`图形界面的组件,别导错包了。

11.3.2 ` List<E>`接口中常用方法

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

1、添加元素

  • `void add(int index, E ele)`:把元素添加到指定位置
  • `boolean addAll(int index, Collection<? extends E> eles)`:把一组元素添加到指定位置

2、删除元素

  • `E remove(int index)`:删除指定位置的元素

3、修改元素

  • `E set(int index, E ele)`:替换[index]位置的元素
  • `default void replaceAll(UnaryOperator<E> operator)`:按指定操作的要求替换元素

4、获取元素

  • `E get(int index)`:返回[index]位置的元素
  • `List subList(int fromIndex, int toIndex)`:返回[fromIndex, toIndex)范围的元素
  • `int indexOf(Object obj)`:查询obj在列表中的位置,如果有重复,返回第1个
  • `int lastIndexOf(Object obj)`:查询obj在列表中的地位,如果有重复,返回最后1个

5、其他方法

  • `default void sort(Comparator<? super E> c) `:对List集合元素进行排序,如果想要通过元素的自然比较器排序,调用sort方法时传入null即可。

示例代码

package com.atguigu.list;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.function.UnaryOperator;

public class TestList {
    @Test
    public void test1(){
/*
        ArrayList是List接口的实现类。
        演示添加add
         */
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("java");

        list.add(0,"atguigu");
        list.add(2,"world");

        System.out.println(list);//[atguigu, hello, world, java]


        List<String> list2 = Arrays.asList("chai", "lin", "yan");

        list.addAll(1,list2);
        System.out.println(list);//[atguigu, chai, lin, yan, hello, world, java]
    }

    @Test
    public void test2(){
 /*
        ArrayList是List接口的实现类。
        演示删除remove(index)
         */
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("java");

        list.remove(0);
        System.out.println(list);
    }

    @Test
    public void test3(){
       /*
        ArrayList是List接口的实现类。
        演示删除
         */
        List<Integer> list =new ArrayList<>();
        list.add(10);
        list.add(20);
        list.add(30);
        list.add(40);

        list.remove(1);//删除[1]位置的元素
        System.out.println(list);//[10, 30, 40]

        //list.remove(30);//删除元素值为30的元素
        list.remove(Integer.valueOf(30));//手动装箱
        System.out.println(list);//[10, 40]
    }

    @Test
    public void test4(){
         /*
        ArrayList是List接口的实现类。
        演示修改替换
         */
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("java");

        list.set(0,"hi");
        System.out.println(list);//[hi, java]

        UnaryOperator<String> u = new UnaryOperator<String>() {
            @Override
            public String apply(String s) {
                return s.toUpperCase();
            }
        };
        list.replaceAll(u);
        System.out.println(list);//[HI, JAVA]
    }

    @Test
    public void test5(){
                 /*
        ArrayList是List接口的实现类.
        演示查询,截取
         */
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("java");
        list.add("world");
        list.add("mysql");
        list.add("java");

        System.out.println(list.get(1));//java
        System.out.println(list.indexOf("java"));//1
        System.out.println(list.lastIndexOf("java"));//4

        List<String> subList = list.subList(1, 3);//[1,3)下标范围的元素
        System.out.println("subList = " + subList);//[java, world]
    }

    @Test
    public void test6(){
        //演示排序
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("java");
        list.add("world");
        list.add("mysql");
        list.add("java");
        System.out.println(list);

        list.sort(null);
        System.out.println(list);

        Comparator<String> c = new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.length()-o2.length();
            }
        };
        list.sort(c);
        System.out.println(list);

    }
}