天天看點

[Guava源碼日報](10)Iterables

版權聲明:本文為部落客原創文章,未經部落客允許不得轉載。 https://blog.csdn.net/SunnyYoona/article/details/71080353

1. 簡介

Iterables類包含了一系列的靜态方法,來操作或傳回Iterable對象。

除非另外說明,每一個Iterables方法都會有一個Iterators的方法。

https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEB8ff27b505c8f99afd714a08f51301107%3Fmethod%3Ddownload%26read%3Dtrue#2-%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90 2. 源碼分析

https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEB8ff27b505c8f99afd714a08f51301107%3Fmethod%3Ddownload%26read%3Dtrue#21-%E6%9E%84%E9%80%A0%E5%99%A8 2.1 構造器

Iterables類隻提供了私有構造器,是以隻能通過靜态方法來使用Iterables類。

public final class Iterables {
  private Iterables() {}           
https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEB8ff27b505c8f99afd714a08f51301107%3Fmethod%3Ddownload%26read%3Dtrue#22-iterable-unmodifiableiterableiterable-iterable 2.2 Iterable unmodifiableIterable(Iterable iterable)

傳回Iterable對象的一個不可變視圖。

public static <T> Iterable<T> unmodifiableIterable(
      final Iterable<T> iterable) {
    checkNotNull(iterable);
    // 判斷是否是UnmodifiableIterable或者ImmutableCollection的執行個體
    if (iterable instanceof UnmodifiableIterable ||
        iterable instanceof ImmutableCollection) {
      return iterable;
    }
    // 否則封裝為UnmodifiableIterable對象
    return new UnmodifiableIterable<T>(iterable);
  }           
https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEB8ff27b505c8f99afd714a08f51301107%3Fmethod%3Ddownload%26read%3Dtrue#23-%E5%86%85%E9%83%A8%E7%B1%BB-class-unmodifiableiterable 2.3 内部類 class UnmodifiableIterable

重寫父類的方法,擷取Iterable不可變視圖

private static final class UnmodifiableIterable<T> extends FluentIterable<T> {
    private final Iterable<T> iterable;
    private UnmodifiableIterable(Iterable<T> iterable) {
      this.iterable = iterable;
    }
    @Override
    public Iterator<T> iterator() {
     // 使用Iterators.unmodifiableIterator實作
      return Iterators.unmodifiableIterator(iterable.iterator());
    }
    @Override
    public String toString() {
      return iterable.toString();
    }
    // no equals and hashCode; it would break the contract!
  }           
https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEB8ff27b505c8f99afd714a08f51301107%3Fmethod%3Ddownload%26read%3Dtrue#24-int-sizeiterable-iterable 2.4 int size(Iterable iterable)

傳回Iterable疊代器中元素個數。如果是iterable是Collection對象(Collection繼承了Iterable類)的執行個體,則會調用size方法;否則使用Iterators.size()方法。

public static int size(Iterable<?> iterable) {
    return (iterable instanceof Collection)
        ? ((Collection<?>) iterable).size()
        : Iterators.size(iterable.iterator());
  }           
https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEB8ff27b505c8f99afd714a08f51301107%3Fmethod%3Ddownload%26read%3Dtrue#25-boolean-containsiterable-iterableobject-element 2.5 boolean contains(Iterable iterable,Object element)

判斷疊代器中是否包含指定元素element。如果是Collection執行個體,使用Collections2.safeContains()方法;否則使用Iterators.contains()方法。

public static boolean contains(Iterable<?> iterable, @Nullable Object element) {
    if (iterable instanceof Collection) {
      Collection<?> collection = (Collection<?>) iterable;
      return Collections2.safeContains(collection, element);
    }
    return Iterators.contains(iterable.iterator(), element);
  }           
https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEB8ff27b505c8f99afd714a08f51301107%3Fmethod%3Ddownload%26read%3Dtrue#26-boolean-removealliterable-removefromcollection-elementstoremove 2.6 boolean removeAll(Iterable removeFrom,Collection elementsToRemove)

從Iterable疊代器中移除給定Collection集合中的所有元素。如果給定參數是Collection執行個體,則使用Collection類的removeAll()方法,否則使用Iterators.removeAll()方法。隻要任意一個元素被移除,即可傳回true。

public static boolean removeAll(
      Iterable<?> removeFrom, Collection<?> elementsToRemove) {
    return (removeFrom instanceof Collection)
        ? ((Collection<?>) removeFrom).removeAll(checkNotNull(elementsToRemove))
        : Iterators.removeAll(removeFrom.iterator(), elementsToRemove);
  }           

執行個體:

@Test
    public void test1(){
        List<String> list = Lists.newArrayList();
        list.add("one");
        list.add("two");
        list.add("three");
        List<String> list2 = Lists.newArrayList();
        list2.add("two");
        list2.add("four");
        System.out.println(Iterables.removeAll(list, list2)); // true
        System.out.println(list.toString()); // [one, three]
    }           
https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEB8ff27b505c8f99afd714a08f51301107%3Fmethod%3Ddownload%26read%3Dtrue#27-boolean-retainalliterable-removefromcollection-elementstoretain 2.7 boolean retainAll(Iterable removeFrom,Collection elementsToRetain)

從Iterable疊代器中保留給定Collection集合中的所有元素(在疊代器中存在),其他移除。如果給定參數是Collection執行個體,則使用Collection類的retainAll()方法,否則使用Iterators.retainAll()方法。隻要任意一個元素被保留,即可傳回true。

public static boolean retainAll(
      Iterable<?> removeFrom, Collection<?> elementsToRetain) {
    return (removeFrom instanceof Collection)
        ? ((Collection<?>) removeFrom).retainAll(checkNotNull(elementsToRetain))
        : Iterators.retainAll(removeFrom.iterator(), elementsToRetain);
  }           
public void test1(){
        List<String> list = Lists.newArrayList();
        list.add("one");
        list.add("two");
        list.add("three");
        List<String> list2 = Lists.newArrayList();
        list2.add("two");
        list2.add("three");
        list2.add("four");
        System.out.println(Iterables.retainAll(list, list2)); // true
        System.out.println(list.toString()); // [two, three]
    }           
https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEB8ff27b505c8f99afd714a08f51301107%3Fmethod%3Ddownload%26read%3Dtrue#28-boolean-removeifiterable-removefrompredicate-predicate 2.8 boolean removeIf(Iterable removeFrom,Predicate predicate)

從Iterable疊代器中移除符合Predicate斷言規則的元素。如果removeFrom是RandomAcesss執行個體,或者是List執行個體,調用removeIfFromRandomAccessList方法;否則調用Iterators.removeIf()方法。

public static <T> boolean removeIf(
            Iterable<T> removeFrom, Predicate<? super T> predicate) {
        if (removeFrom instanceof RandomAccess && removeFrom instanceof List) {
            return removeIfFromRandomAccessList(
                    (List<T>) removeFrom, checkNotNull(predicate));
        }
        return Iterators.removeIf(removeFrom.iterator(), predicate);
    }
    private static <T> boolean removeIfFromRandomAccessList(
            List<T> list, Predicate<? super T> predicate) {
        // Note: Not all random access lists support set() so we need to deal with
        // those that don't and attempt the slower remove() based solution.
        int from = 0;
        int to = 0;
        // 不符合斷言to+1,from每輪都要+1
        for (; from < list.size(); from++) {
            T element = list.get(from);
            // 判斷是否符合斷言 如果符合則傳回true
            if (!predicate.apply(element)) {
                if (from > to) {
                    try {
                        // element元素與位置為to的元素互換
                        list.set(to, element);
                    } catch (UnsupportedOperationException e) {
                        slowRemoveIfForRemainingElements(list, predicate, to, from);
                        return true;
                    }
                }
                to++;
            }
        }
        // Clear the tail of any remaining items
        // 經過以上幾輪之後,待移除的元素放在末尾(to之後)
        list.subList(to, list.size()).clear();
        return from != to;
    }           

并不是所有的random access lists支援set()方法,是以我們需要單獨處理,使用 slowRemoveIfForRemainingElements方法。

public void test1(){
        List<String> list = Lists.newArrayList();
        list.add("one");
        list.add("three");
        list.add("two");
        list.add("two");
        list.add("three");
        List<String> list2 = Lists.newArrayList();
        list2.add("two");
        list2.add("three");
        list2.add("four");
        System.out.println(Iterables.removeIf(list, new Predicate<String>() {
            @Override
            public boolean apply(String input) {
                return input.length() == 5;
            }
        })); // true
        System.out.println(list.toString()); // [one, two, two]
    }           
https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEB8ff27b505c8f99afd714a08f51301107%3Fmethod%3Ddownload%26read%3Dtrue#29-removefirstmatchingiterable-removefrompredicate-predicate 2.9 removeFirstMatching(Iterable removeFrom,Predicate predicate)

從疊代器中移除第一個滿足斷言的元素。Iterable都會有一個對應的Iterator,使用Iterator的方法實作。

static <T> T removeFirstMatching(Iterable<T> removeFrom, Predicate<? super T> predicate) {
    checkNotNull(predicate);
    Iterator<T> iterator = removeFrom.iterator();
    while (iterator.hasNext()) {
      T next = iterator.next();
      if (predicate.apply(next)) {
        iterator.remove();
        return next;
      }
    }
    return null;
  }           
https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEB8ff27b505c8f99afd714a08f51301107%3Fmethod%3Ddownload%26read%3Dtrue#210-boolean-elementsequaliterable-iterable1iterable-iterable2 2.10 boolean elementsEqual(Iterable iterable1,Iterable iterable2)

判斷兩個疊代器是否相等。如果兩個疊代器都是Collection執行個體,并且元素個數不相同傳回false;否則調用 Iterators.elementsEqual方法。

public static boolean elementsEqual(
      Iterable<?> iterable1, Iterable<?> iterable2) {
    if (iterable1 instanceof Collection && iterable2 instanceof Collection) {
      Collection<?> collection1 = (Collection<?>) iterable1;
      Collection<?> collection2 = (Collection<?>) iterable2;
      if (collection1.size() != collection2.size()) {
        return false;
      }
    }
    return Iterators.elementsEqual(iterable1.iterator(), iterable2.iterator());
  }           

繼續閱讀