java核心知识之集合详解一(底层接口)

集合

集合类是用来存放某类对象的。集合类有一个共同特点,就是它们只容纳对象(实际上是对象名,即指向地址的指针)。这一点和数组不同,数组可以容纳对象和简单数据。如果在集合类中既想使用简单数据类型,又想利用集合类的灵活性,就可以把简单数据类型数据变成该数据类型类的对象,然后放入集合中处理,但这样执行效率会降低。比如说基本数据类型的封装类,int类型对应的封装类为Integer, long类型对应的封装类为Long类型

集合类容纳的对象都是Object类的实例(所有对象继承于Object类),一旦把一个对象置入集合类中,它的类信息将丢失,也就是说,集合类中容纳的都是指向Object类对象的指针。这样的设计是为了使集合类具有通用性,因为Object类是所有类的祖先,所以可以在这些集合中存放任何类而不受限制。当然这也带来了不便,这令使用集合成员之前必须对它重新造型。

Collection接口

Collection是一个基本的集合接口,Collection中可以容纳一组集合元素(Element),Collection有两个重要的子接口List和SetList表达一个有序的集合List中的每个元素都有索引,使用此接口能够准确的控制每个元素插入的位置。用户也能够使用索引来访问List中的元素,List类似于Java的数组Set接口的特点是不能包含重复的元素。对Set中任意的两个元素element1和element2都有element1.equals(element2)==false。另外,Set最多有一个null元素。

Collection继承树
在这里插入图片描述

Collection的Api文档

boolean add(E e) 该方法用于向集合里添加一个元素。如果集合对象被添加操作改变了,则返回 trueboolean addAll(Collection<? extends E> c)该方法把集合 c 里的所有元素添加到指定集合里。 如果集合对象被添加操作改变了 , 则返回 truevoid clear() 清除集合里的所有元素,将集合长度变为 0boolean contains(Object o) 返回集合里是否包含指定元素 。
  
boolean containsAll(Collection<?> c) 返回集合里是否包含集合 c 里的所有元素。 

boolean equals(Object o) 将指定的对象与此集合进行比较,以进行相等性 

int hashCode() 返回此集合的哈希代码值。 
 
boolean isEmpty() 返回集合是否为空。当集合长度为 0 时返回 true ,否则返回 false 。

Iterator<E> iterator() 返回此集合中的元素的迭代器。 

default Stream<E> parallelStream() 返回一个可能并行 Stream与集合的来源。
  
boolean remove(Object o)  删除集合中的指定元素。当集合中包含了一个或多个元素时,该方法只删除第一个符合条件的元素 ,该方法将返回trueboolean removeAll(Collection<?> c) 从集合中删除集合 c 里包含的所有元素( 相当于用调用该方法
的集合减集合 c) ,如果删除了一个或一个以上的元素,则该方法返回 truedefault boolean removeIf(Predicate<? super E> filter) 删除满足给定谓词的这个集合的所有元素。
  
boolean retainAll(Collection<?> c) 从集合中删除集合 c 里包含的所有元素( 相当于用调用该方法的集合减集合 c) ,如果删除了一个或一个以上的元素,则该方法返回 trueint size() 返回此集合中的元素的数目。  

default Spliterator<E> spliterator() 创建此集合中的元素的 Spliterator。  

default Stream<E> stream() 返回一个序列 Stream与集合的来源。  

Object[] toArray() 返回包含此集合中所有元素的数组。  

< T > T[] toArray(T[] a) 返回包含此集合中所有元素的数组;返回数组的运行时类型是指定的数组的运行时类型。  

实例代码

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;

/**
 * @Author: 随风飘的云
 * @Description:
 * @Date: 2022/3/18 0:26
 * @Modified By:
 */
public class CollectionTest
{
    
    
    public static void main(String[] args){
    
    
        Collection c = new ArrayList();
        // 添加元素
        c.add("孙悟空");
        // 虽然集合里不能放基本类型的值,但Java支持自动装箱
        c.add(6);
        System.out.println("c集合的元素个数为:" + c.size()); // 输出2
        // 删除指定元素
        c.remove(6);
        System.out.println("c集合的元素个数为:" + c.size()); // 输出1
        // 判断是否包含指定字符串
        System.out.println("c集合的是否包含\"孙悟空\"字符串:"
                + c.contains("孙悟空")); // 输出true
        c.add("轻量级Java EE企业应用实战");
        System.out.println("c集合的元素:" + c);
        Collection books = new HashSet();
        books.add("轻量级Java EE企业应用实战");
        books.add("疯狂Java讲义");
        System.out.println("c集合是否完全包含books集合?"
                + c.containsAll(books)); // 输出false
        // 用c集合减去books集合里的元素
        c.removeAll(books);
        System.out.println("c集合的元素:" + c);
        // 删除c集合里所有元素
        c.clear();
        System.out.println("c集合的元素:" + c);
        // 控制books集合里只剩下c集合里也包含的元素
        books.retainAll(c);
        System.out.println("books集合的元素:" + books);
    }
}

结果
在这里插入图片描述

Map接口

Map没有继承Collection接口,与Collection是并列关系。Map提供键(key)到值(value)的映射。一个Map中不能包含相同的键,每个键只能映射一个值。

Map集合继承树
在这里插入图片描述

Map的Api接口

void clear() 从这个映射中移除所有的映射(可选操作)。
  
default V compute(K key, BiFunction<? super K,? super V,? extends V> remappingFunction) 试图计算出指定键和当前的映射值的映射(或 null如果没有当前映射)。 
 
default V computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction) 如果指定的键是不是已经与价值相关的(或映射到 null),尝试使用给定的映射功能,进入到这个Map除非 null计算其价值。  

default V computeIfPresent(K key, BiFunction<? super K,? super V,? extends V>remappingFunction) 如果指定键的值是存在和非空的,尝试计算一个新的映射,给出了键和它当前的映射值。 
 
boolean containsKey(Object key) 返回 true如果这Map包含一个指定的键映射。  

boolean containsValue(Object value) 返回 true如果映射到指定的值的一个或多个键。
  
Set<Map.Entry<K,V>> entrySet() 返回一个 Set视图的映射包含在这个Map。 
 
boolean equals(Object o) 将指定的对象与此映射的相等性进行比较。  

default void forEach(BiConsumer<? super K,? super V> action) 在该映射中的每个条目执行给定的操作,直到所有的条目被处理或操作抛出异常。  

V get(Object key) 返回指定的键映射的值,或 null如果这个Map不包含的键映射。 
 
default V getOrDefault(Object key, V defaultValue) 返回指定的键映射的值,或 defaultValue如果这个Map不包含的键映射。  

int hashCode() 返回此映射的哈希代码值。
  
boolean isEmpty() 返回 true如果这个Map不包含键值的映射。 
 
Set<K> keySet() 返回一个 Set的关键视图包含在这个Map。 
 
default V merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction) 如果指定的键已与值相关联的值或与空值相关联的,则将其与给定的非空值关联。 
 
V put(K key, V value) 将指定的值与此映射中的指定键关联(可选操作)。 
 
void putAll(Map<? extends K,? extends V> m) 从指定的映射到这个Map(可选操作)复制所有的映射。 
 
default V putIfAbsent(K key, V value) 如果指定的键是不是已经与价值相关的(或映射到 null)将其与给定的值并返回 null,否则返回当前值。  

V remove(Object key) 如果存在(可选操作),则从该Map中移除一个键的映射。  

default boolean remove(Object key, Object value) 仅当它当前映射到指定的值时,为指定的键移除条目。
  
default V replace(K key, V value) 仅当它当前映射到某一值时,替换指定的键的条目。
  
default boolean replace(K key, V oldValue, V newValue) 仅当当前映射到指定的值时,替换指定的键的条目。  

default void replaceAll(BiFunction<? super K,? super V,? extends V> function) 将每个条目的值替换为在该项上调用给定函数的结果,直到所有的条目都被处理或函数抛出异常。 
 
int size() 返回这个映射中的键值映射的数目。  

Collection<V> values() 返回一个 Collection视图的值包含在这个Map。

集合的遍历

使用Lambda表达式遍历

Java 8 为Iterable 接口新增了 一个 forEach(Consumer action)默认方法 , 该方法所需参数的类型是一个函数式接口,而Iterable 接口是 Collection 接口的父接口 ,因此 Collection 集合也可直接调用该方法。当程序调用 Iterable 的 forEach(Consumer action)遍历集合元素 时, 程序会依次将集合元素传给
Consumer 的 accept(T t)方法(该接口中唯一 的抽 象方法)。正因Consumer 是函数式接口,因此可以使用 Lambda 表达式来遍历集合元素。

实例代码

import java.util.Collection;
import java.util.HashSet;

public class CollectionEach{
    
    
    public static void main(String[] args){
    
    
        // 创建一个集合
        Collection books = new HashSet();
        books.add("轻量级Java EE企业应用实战");
        books.add("疯狂Java讲义");
        books.add("疯狂Android讲义");
        // 调用forEach()方法遍历集合
        books.forEach(obj -> System.out.println("迭代集合元素:" + obj));
    }
}

结果:
在这里插入图片描述

使用java8增强的Iterator遍历集合元素

Iterator 接口也是 Java 集合框架的成员,Iterator 则主要用于遍历( 即迭代访 问 ) Collection集合中的元素, Iterator 对象也被称为迭代器。

Iterator的API文档

boolean hasNext(): 如果被迭代的集合元素还没有被遍历完 ,则返回 true 。

Object next(): 返回集合里的 下一个元素。

void remove(): 删除集合里上一次next方法返回的元素。

void forEachRemaining(Consumer action) ,这是 Java 8 为Iterator新增的默认方法, 该方法可使用Lambda 表达式来遍历集合元素。

实例代码

import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

public class IteratorTest {
    
    
    public static void main(String[] args) {
    
    
        // 创建集合、添加元素的代码与前一个程序相同
        Collection books = new HashSet();
        books.add("轻量级Java EE企业应用实战");
        books.add("疯狂Java讲义");
        books.add("疯狂Android讲义");
        // 获取books集合对应的迭代器
        Iterator it = books.iterator();
        while(it.hasNext())
        {
    
    
            // it.next()方法返回的数据类型是Object类型,因此需要强制类型转换
            String book = (String)it.next();
            System.out.println(book);
            if (book.equals("疯狂Java讲义"))
            {
    
    
                // 从集合中删除上一次next方法返回的元素
                it.remove();
            }
            // 对book变量赋值,不会改变集合元素本身
            book = "测试字符串";   //①
        }
        System.out.println(books);
    }
}

结果:
在这里插入图片描述
当使用 Iterator 迭代访问 Collection 集合元素 时, Collection 集合里 的元素不能被改变 ,只有通过Iterator 的 remove()方法删 除 上 一 次 next()方法返回 的集合元素才可以;否则将会发生异常。

实例代码

import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

public class IteratorErrorTest {
    
    
    public static void main(String[] args)
    {
    
    
        // 创建集合、添加元素的代码与前一个程序相同
        Collection books = new HashSet();
        books.add("a");
        books.add("c");
        books.add("b");
        System.out.println(books);
        System.out.println();
        // 获取books集合对应的迭代器
        Iterator it = books.iterator();
        while(it.hasNext())
        {
    
    
            String book = (String)it.next();
            if (book.equals("a"))
            {
    
    
                // 使用Iterator迭代过程中,不可修改集合元素,下面代码引发异常
                books.remove(book);
                System.out.println(book.hashCode());
            }
        }
    }
}

结果
在这里插入图片描述

使用Lambda表达式遍历Iterator

实例代码

import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

public class IteratorEach {
    
    
    public static void main(String[] args) {
    
    
        // 创建集合、添加元素的代码与前一个程序相同
        Collection books = new HashSet();
        books.add("我");
        books.add("你");
        books.add("他");
        // 获取books集合对应的迭代器
        Iterator it = books.iterator();
        // 使用Lambda表达式(目标类型是Comsumer)来遍历集合元素
        it.forEachRemaining(obj -> System.out.println("迭代集合元素:" + obj));
    }
}

结果
在这里插入图片描述

Stream操作集合

java8新增了Stream, IntStream, LongStream, DoubleStream等流式Api,其中Stream是通用的流式APi,而其他的分别代表为int,long,double的流。

Stream的方法分类

1、中间方法: 中间操作允许流保持打开状态,并允许直接调用后续方法 。
2、末端方法: 末端方法是对流的最终操作 。 当对某个 Stream 执行末端方法后,该流将被"消耗"且不再可用

Stream的方法特征

1、状态的方法: 这种方法会给流增加一些新的属性,比如元素的唯一性、元素的最大数量、保证元素以排序的方式被处理等 。 有状态的方法往往需要更大的性能开销 。
2、短路方法 : 短路方法可以尽早结束对流的操作,不必检查所有的元素 。

Stream的Api方法

Stram的中间APi方法

filter(Predicate predicate): 过滤 Stream 中所有不符合 predicate 的元素 。

mapToXxx(ToXxxFunction m叩per): 使用 ToXxxFunction 对流中的元素执行一对一 的转换,该方
法返回的新流中包含了 ToXxxFunction 转换生成的所有元素 。

peek(Consumer action): 依次对每个元素执行一些操作,该方法返回的流与原有流包含相同的元素 。 该方法主要用于调试。

distinct(): 该方法用于排序流中所有重复的元素(判断元素重复的标准是使用 equals() 比较返回true) 。 这是一个有状态的方法 。

sorted(): 该方法用于保证流中的元素在后续的访问中处于有序状态 。 这是一个有状态的方法 。

limit(long maxSize): 该方法用于保证对该流的后续访

Stream的末端API方法

forEach(Consumer action): 遍历流中所有元素,对每个元素执行 action 。

toArray(): 将流中所有元素转换为一个数组 。

reduce(): 该方法有三个重载的版本,都用于通过某种操作来合并流中的元素 。

 min():  返回流中所有元素的最小值 。
 
max():  返回流中所有元素的最大值 。

count(): 返回流中所有元素的数量。

anyMatch(Predicate predicate): 判断流中是否至少包含一个元素符合 Predicate 条件 

allMatch(Predicate predicate): 判断流中是否每个元素都符合 Predicate 条件。

noneMatch(predicate predicate): 判断流中是否所有元素都不符合 Predicate 条件。

findFirst(): 返回流中的第一个元素。

findAny(): 返回流中的任意 一个元素。

实例代码

import java.util.Collection;
import java.util.HashSet;

/**
 * @author: 随风飘的云
 * @date 2022/03/18 22:20
 */
public class CollectionStream {
    
    
    public static void main(String[] args) {
    
    
        Collection collection = new HashSet();

        collection.add("小红是一个三年级的学生");
        collection.add("小红的爸爸是一个教师");
        collection.add("语文,数学,英语是小红必须学的科目");
        collection.add("小红是个男孩");

        System.out.print("测试1:");
        System.out.println(
                // 设置Stream流
                collection.stream()
                        // 过滤
                        .filter(count
                                // 判断Collection中包含有几个小红(4个)
                                -> ((String) count).contains("小红")).count());

        // 输出1(判断语句中包含有语文的句子有多少个)
        System.out.print("测试2:");
        System.out.println(collection.stream().filter(
                count -> ((String) count).contains("语文")).count());

        // 输出2(判断语句长度大于10的有多少个)
        System.out.print("测试3:");
        System.out.println(collection.stream().filter(
                str -> ((String) str).length() > 10).count());

        //先调用Collection对象的stream()方法将集合转换为Stream
        //再调用 Stream的 mapToInt ()方法获取原有的 Stream 对应的 IntStream
        // 输出每一个句子的长度
        System.out.println();
        collection.stream().forEach(System.out::println);
        collection.stream().mapToInt(len -> ((String) len).length()).forEach(System.out::println);
    }
}

结果:
在这里插入图片描述

集合类的好处

使用Java提供的集合类有如下功能:

(1)降低编程难度:在编程中会经常需要链表、向量等集合类,如果自己动手写代码实现这些类,需要花费较多的时间和精力。调用Java中提供的这些接口和类,可以很容易的处理数据。
(2)提升程序的运行速度和质量:Java提供的集合类具有较高的质量,运行时速度也较快。使用这些集合类提供的数据结构,程序员可以从“重复造轮子”中解脱出来,将精力专注于提升程序的质量和性能。
(3)无需再学习新的APl:借助泛型,只要了解了这些类的使用方法,就可以将它们应用到很多数据类型中。如果知道了LinkedList的使用方法,也会知道LinkedList怎么用,则无需为每一种数据类型学习不同的API。
(4)增加代码重用性:也是借助泛型,就算对集合类中的元素类型进行了修改,集合类相关的代码也几乎不用修改。

猜你喜欢

转载自blog.csdn.net/m0_46198325/article/details/123515855
今日推荐