集合的接口到底干啥用

从今天开始,我要重新总结一遍java里面有关于集合的东西,便于自己复习,而且春招也在这里,非常可怕,我要认认真真学习了。疫情让我开不了学压哈哈哈。美哉美哉。

先告诉自己,这篇文章没太多实用性,只要了解几个重点接口的关系就行了。

好了,废话不多说了,先看一张图
在这里插入图片描述
这是集合里面最常见的一张图,各种类和接口都在上面。可以看到,最顶层的是Iterator,接着是Collection和ListIterator。那么ListIterator我们不说,暂且先看看另外两个,扒光他们看看😄😄😄😄😄😄😄😄👨👨👨👨👨
GOGOGOGO~~~~

Iterator

迭代器作用于集合,是用来遍历集合元素的对象。迭代器不是Java独有的,大部分高级语言都提供了迭代器来遍历集合。实际上,迭代器是一种设计模式:

迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。

迭代器封装了对集合的遍历,使得不用了解集合的内部细节,就可以使用同样的方式遍历不同的集合。

什么都不说,就只看源码:

public interface Iterator<E> {
    /**
     * 这个方法一般是在next方法之前使用,来判断迭代器还有没有元素
     * 
     */
    boolean hasNext();

    /**
     *返回下一个元素
     *如果已经没有元素了就会@throws NoSuchElementException 
     */
    E next();

    /**
     * 移除上一次调用next方法返回一个元素,也就是说他和next方法紧密相连,如果没有在之前调用next,就会出错
   
     */
    default void remove() {
        throw new UnsupportedOperationException("remove");
    }

    /**
     * 
     * 这个方法是JDK1.8才有的,这个可以调用然后传入一个lambda表达式,它相当于不用写循环就可以遍历,然后根据lambda的逻辑操作
     * 
     */
    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}

foreachRemaining方法使用

当然,每个集合实现可能不同,到时候总结看看。
在这里插入图片描述

插一段小话

看看这个
在这里插入图片描述
最上面的图,好像是Collection和Iterator有关系,而现在怎么又和Iterable有关系了。看看源码就知道怎么回事了。走,看看Iterable

Iterable

public interface Iterable<T> {
    /**
     *实现接口这个方法,可以返回迭代器,所以这里看清楚了,Iterable有个方法返回Iterator需要我们去实现的。
     */
    Iterator<T> iterator();

    /**
     * 这个是jdk1.8的一个语法糖的东西,这个方法在编译阶段会以迭代器去遍历元素,但是我们仍然可以使用foreach去使用
     *
     *其实和这种形式是一样的效果,他的默认实现就是这样。
     *     for (T t : this)
     *         action.accept(t);
     * 		}  
     */
    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }

    /**
     * 
     */
    default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}

上面的代码我们可以看见Iterable的iterator方法返回的是Iterator。这样关系就清楚了吧
那么我们再仔细看看Collection接口

Collection

哇,原来是Collection接口又继承了Iterable接口,那么理应实现了Collection接口的话,就要实现iterator方法,这样就可以得到一个迭代器Iterator了。但是这个Iterator的方法没有实现怎么吧。不急,以后会看到的,今天只管Collection接口
public interface Collection<E> extends Iterable<E> {
      /**
     * 返回集合的大小
     */
    int size();    
    boolean isEmpty();   
    boolean contains(Object o);
    Iterator<E> iterator();
    Object[] toArray();
    <T> T[] toArray(T[] a);
    boolean add(E e);

 
    boolean remove(Object o);  
    boolean containsAll(Collection<?> c);    
    boolean addAll(Collection<? extends E> c);
    boolean removeAll(Collection<?> c);  
    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;
    }
    
    boolean retainAll(Collection<?> c);


    void clear();


    // Comparison and hashing

   
  //hashcode和equals方法要重点注意
    boolean equals(Object o);   
    int hashCode();   
   
    @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);
    }
}

源代码没有多少行,目的在于搞清楚三者关系,下面慢慢深入其他的接口和抽象类和实现类。

但是呢,其实以后会看到,在其他的链表和树还有Set这些都可能用到Map的实现
那Map接口又是啥呢

Map

我们都知道Map是一种键值对的形式存在的,比如Redis,MongoDB,JSON都运用了其中的原理,那我们先来看看java里面的Map接口到底有什么东西,可以实现的。



package java.util;

import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.io.Serializable;

/**
 * 一个Map对象不能有多个相同key,一个key最多对应一个value
public interface Map<K,V> {
   //返回Map的个数
    int size();
    boolean isEmpty();
    boolean containsKey(Object key);
    boolean containsValue(Object value);   
    V get(Object key);
    V put(K key, V value);  
    V remove(Object key);   
    void putAll(Map<? extends K, ? extends V> m);   
    void clear();
    //这里居然还用到了集合里面的东西
    Set<K> keySet();
 
    Collection<V> values();

    Set<Map.Entry<K, V>> entrySet();

    /**
     * 一个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());
        }
    }
    
    boolean equals(Object o);

  
    int hashCode();

  	//如果存在就获取,如果没有就又一个默认值
    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;
    }
}

posted @ 2020-02-19 17:54  ongbo  阅读(28)  评论(0)    收藏  举报