【java集合一】根接口Collection、Map

       Java集合类是一种非常实用的工具类,主要用于保存、盛装其它数据(集合里只能保存对象),因此集合类也被成为容器类。所有的集合类都位于java.util包下,在java.util.concurrent下还提供了一些支持多线程的集合类。Java的集合类主要由两个接口派生而来:Collection和Map,这两个是Java集合框架的根接口。

一、Collection接口


        Collection派生出三个子接口,Set代表不可重复的无序集合、List代表可重复的有序集合、Queue是java提供的队列实现;Collection是最基本的集合接口,它提供了一些通用的方法,供子接口调用。

        Collection源码分析如下:

// 位于java.util包下
package java.util;

import java.util.function.Predicate; // 函数式接口,广泛用在支持lambda表达式的API中
import java.util.stream.Stream; // 数据流接口,定义了众多Stream应该具有的行为
import java.util.stream.StreamSupport; //提供了底层的一些用于操作Stream的方法,如果不需要创建自己的Stream,一般不需要使用它。

// 继承于接口Iterable迭代器,即所有Collection集合体系中的集合类,都可以使用forEach进行循环遍历
public interface Collection<E> extends Iterable<E> {
    // 1.查询类操作
    int size(); // 返回元素个数
    boolean isEmpty(); // 判断集合是否为空
    boolean contains(Object o); // 判断是否包含元素 o
    Iterator<E> iterator(); // 返回集合类的迭代器
    Object[] toArray(); // 将集合转换为数组
    <T> T[] toArray(T[] a); // 转换为具体某一类型的数组

    // 2.修改类操作
    boolean add(E e); // 往集合中添加元素 e
    boolean remove(Object o); // 删除元素 o

    // 3.批量操作
    boolean containsAll(Collection<?> c); // 判断 c 是否包含在集合中
    boolean addAll(Collection<? extends E> c); // 将 c 中所有元素添加到集合中
    boolean removeAll(Collection<?> c); // 移除集合中所包含的 c 中的所有元素
    boolean retainAll(Collection<?> c); //移除所有不包含在 c 中的所有元素,即只留下两个集合共有的元素
    void clear(); // 清除集合中所有元素
    // 删除满足 filter 条件的元素
    default boolean removeIf(Predicate<? super E> filter) {
        Objects.requireNonNull(filter);
        boolean removed = false;
        final Iterator<E> each = iterator();
        while (each.hasNext()) {
            if (filter.test(each.next())) {
                each.remove();
                removed = true;
            }
        }
        return removed;
    }

    // 4.比较和散列
    boolean equals(Object o); // 判断集合和对象 o 是否相等
    int hashCode(); // 返回该集合的 hashcode 值
    // 重写了 Iterable 接口的 Spliterator 方法
    @Override
    default Spliterator<E> spliterator() {
        return Spliterators.spliterator(this, 0);
    }
    // 在这个集合上返回一个连续的代码流
    default Stream<E> stream() {
        return StreamSupport.stream(spliterator(), false);
    }
    // 在这个集合上返回一个并行的代码流
    default Stream<E> parallelStream() {
        return StreamSupport.stream(spliterator(), true);
    }
}

二、Map接口


        Map实现类都用于保存具有映射关系的数据,它们保存的数据都是key-value对,如果要查找Map中的数据,总是根据key来获取,所以key是不可重复的,它用于标识集合里的每项数据。

        Map源码分析如下:

// 位于java.util包下
package java.util;

import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.io.Serializable; // 通过实现该接口以启用其序列化功能

// Map 接口, K 为键, V 为值
public interface Map<K,V> {
    // 1.查询操作
    int size(); // 返回元素个数
    boolean isEmpty(); // 判断是否为空
    boolean containsKey(Object key); // 判断是否包含键 key
    boolean containsValue(Object value); // 判断是否包含值 value
    V get(Object key); //返回键 key 对应的值

    // 2.修改操作
    V put(K key, V value); // 添加元素, 元素为 (key,value)
    V remove(Object key); // 移除键为 key 的元素


    // 3.批量操作
    void putAll(Map<? extends K, ? extends V> m); // 将 m 中所有元素添加到集合中
    void clear(); // 清空集合


    // 4.集合视图
    Set<K> keySet(); // 返回 key 的集合视图
    Collection<V> values(); // 返回 value 的集合视图
    Set<Map.Entry<K, V>> entrySet(); //返回元素 Entry<K,V> 的集合视图
    // 集合实体,Map的内部集合,对应Map中的一个元素
    interface Entry<K,V> {
        K getKey();
        V getValue();
        V setValue(V value);
        boolean equals(Object o);
        int hashCode();
        public static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K,V>> comparingByKey() {
            return (Comparator<Map.Entry<K, V>> & Serializable)
                    (c1, c2) -> c1.getKey().compareTo(c2.getKey());
        }

        public static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K,V>> comparingByValue() {
            return (Comparator<Map.Entry<K, V>> & Serializable)
                    (c1, c2) -> c1.getValue().compareTo(c2.getValue());
        }

        public static <K, V> Comparator<Map.Entry<K, V>> comparingByKey(Comparator<? super K> cmp) {
            Objects.requireNonNull(cmp);
            return (Comparator<Map.Entry<K, V>> & Serializable)
                    (c1, c2) -> cmp.compare(c1.getKey(), c2.getKey());
        }

        public static <K, V> Comparator<Map.Entry<K, V>> comparingByValue(Comparator<? super V> cmp) {
            Objects.requireNonNull(cmp);
            return (Comparator<Map.Entry<K, V>> & Serializable)
                    (c1, c2) -> cmp.compare(c1.getValue(), c2.getValue());
        }
    }

    // 5.比较和散列
    boolean equals(Object o); // 判断集合和对象 o 是否相等
    int hashCode(); // 返回该集合的 hashcode 值

    // 6.JDK8出现的新方法 - default新特性
    default V getOrDefault(Object key, V defaultValue) {
        V v;
        return (((v = get(key)) != null) || containsKey(key))
                ? v
                : defaultValue;
    }

    default void forEach(BiConsumer<? super K, ? super V> action) {
        Objects.requireNonNull(action);
        for (Map.Entry<K, V> entry : entrySet()) {
            K k;
            V v;
            try {
                k = entry.getKey();
                v = entry.getValue();
            } catch(IllegalStateException ise) {
                // this usually means the entry is no longer in the map.
                throw new ConcurrentModificationException(ise);
            }
            action.accept(k, v);
        }
    }

    default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
        Objects.requireNonNull(function);
        for (Map.Entry<K, V> entry : entrySet()) {
            K k;
            V v;
            try {
                k = entry.getKey();
                v = entry.getValue();
            } catch(IllegalStateException ise) {
                // this usually means the entry is no longer in the map.
                throw new ConcurrentModificationException(ise);
            }

            // ise thrown from function is not a cme.
            v = function.apply(k, v);

            try {
                entry.setValue(v);
            } catch(IllegalStateException ise) {
                // this usually means the entry is no longer in the map.
                throw new ConcurrentModificationException(ise);
            }
        }
    }

    default V putIfAbsent(K key, V value) {
        V v = get(key);
        if (v == null) {
            v = put(key, value);
        }

        return v;
    }

    default boolean remove(Object key, Object value) {
        Object curValue = get(key);
        if (!Objects.equals(curValue, value) ||
                (curValue == null && !containsKey(key))) {
            return false;
        }
        remove(key);
        return true;
    }

    default boolean replace(K key, V oldValue, V newValue) {
        Object curValue = get(key);
        if (!Objects.equals(curValue, oldValue) ||
                (curValue == null && !containsKey(key))) {
            return false;
        }
        put(key, newValue);
        return true;
    }

    default V replace(K key, V value) {
        V curValue;
        if (((curValue = get(key)) != null) || containsKey(key)) {
            curValue = put(key, value);
        }
        return curValue;
    }

    default V computeIfAbsent(K key,
                              Function<? super K, ? extends V> mappingFunction) {
        Objects.requireNonNull(mappingFunction);
        V v;
        if ((v = get(key)) == null) {
            V newValue;
            if ((newValue = mappingFunction.apply(key)) != null) {
                put(key, newValue);
                return newValue;
            }
        }

        return v;
    }

    default V computeIfPresent(K key,
                               BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
        Objects.requireNonNull(remappingFunction);
        V oldValue;
        if ((oldValue = get(key)) != null) {
            V newValue = remappingFunction.apply(key, oldValue);
            if (newValue != null) {
                put(key, newValue);
                return newValue;
            } else {
                remove(key);
                return null;
            }
        } else {
            return null;
        }
    }

    default V compute(K key,
                      BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
        Objects.requireNonNull(remappingFunction);
        V oldValue = get(key);

        V newValue = remappingFunction.apply(key, oldValue);
        if (newValue == null) {
            // delete mapping
            if (oldValue != null || containsKey(key)) {
                // something to remove
                remove(key);
                return null;
            } else {
                // nothing to do. Leave things as they were.
                return null;
            }
        } else {
            // add or replace old mapping
            put(key, newValue);
            return newValue;
        }
    }

    default V merge(K key, V value,
                    BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
        Objects.requireNonNull(remappingFunction);
        Objects.requireNonNull(value);
        V oldValue = get(key);
        V newValue = (oldValue == null) ? value :
                remappingFunction.apply(oldValue, value);
        if(newValue == null) {
            remove(key);
        } else {
            put(key, newValue);
        }
        return newValue;
    }
}

三、defalut 扩展方法(JDK8新特性)

        与以前的集合类相比,JDK8的新特性之一就是提供了很多 default 方法,这些方法拥有具体的实现,子类可以直接调用这些方法的默认实现。defalut方法对Java集合API进行了优化升级,并且在JDK与Lambda表达式的结合中起到了至关重要的作用。

示例1:

        A 接口中定义了一个 hello() 方法,B 类实现 A 接口,则 B 默认实现了 A 中的 hello() 方法

// A 接口中定义了一个用defalut修饰的 hello 方法
public interface A {
    default void hello(){
        System.out.println("调用 A 接口的 hello() ");
    }
}
// B 类实现 A 接口
public class B implements A {}
public class defaultTest {
    public static void main(String[] args) {
        B b = new B();
        b.hello(); // B 类调用了 A 接口中 hello() 方法的默认实现
    }
}


示例2:

        A 接口中定义了一个 defaul 修饰的 hello() 方法,B 接口中也有一个 defaul 修饰的 hello() 方法,defaulTest 同时实现 A、B 接口,则 defaultTest中必须重写 hello() 方法,否则报错

public interface A {
    default void hello(){
        System.out.println("调用 A 接口的 hello() ");
    }
}
public interface B {
    default void hello(){
        System.out.println("调用 B 接口的 hello() ");
    }
}
public class defaultTest implements A,B{
    public void hello(){
        System.out.println("调用 dafultTest 接口的 hello() "); // 调用自身hello方法
        A.super.hello(); // A 接口的 hello 方法
        B.super.hello(); // B 接口的 hello 方法
    }
    public static void main(String[] args) {
        defaultTest test = new defaultTest();
        test.hello();
    }
}
        接口一般没有方法的具体实现,而java又是一种单继承语言,JDK8中加入的这种新特性,不知道算不算在变相的实现多继承。。。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值