溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

怎么在Java中利用Set&List實現(xiàn)迭代器

發(fā)布時間:2021-05-27 18:05:05 來源:億速云 閱讀:179 作者:Leah 欄目:編程語言

本篇文章給大家分享的是有關(guān)怎么在Java中利用Set&List實現(xiàn)迭代器,小編覺得挺實用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

ArrayList

private class Itr implements Iterator<E> {
    int cursor;    // index of next element to return
    int lastRet = -1; // index of last element returned; -1 if no such
    int expectedModCount = modCount;

    // prevent creating a synthetic constructor
    Itr() {}

    public boolean hasNext() {
      return cursor != size;
    }

    @SuppressWarnings("unchecked")
    public E next() {
      checkForComodification();
      int i = cursor;
      if (i >= size)
        throw new NoSuchElementException();
      Object[] elementData = ArrayList.this.elementData;
      if (i >= elementData.length)
        throw new ConcurrentModificationException();
      cursor = i + 1;
      return (E) elementData[lastRet = i];
    }

    public void remove() {
      if (lastRet < 0)
        throw new IllegalStateException();
      checkForComodification();

      try {
        ArrayList.this.remove(lastRet);
        cursor = lastRet;
        lastRet = -1;
        expectedModCount = modCount;
      } catch (IndexOutOfBoundsException ex) {
        throw new ConcurrentModificationException();
      }
    }
  }

從代碼中我們不難看出迭代器維護上一次return的元素下邊和下一個將要return的元素下標(biāo),并且迭代器在進行修改操作時會檢查在本次操作與上次操作之間是否有迭代器以外的操作,并且適時拋出ConcurrentModificationException(并發(fā)修改異常)來阻止更多錯誤的發(fā)生

LinkedList

private class ListItr implements ListIterator<E> {
    private Node<E> lastReturned;
    private Node<E> next;
    private int nextIndex;
    private int expectedModCount = modCount;

    ListItr(int index) {
      // assert isPositionIndex(index);
      next = (index == size) ? null : node(index);
      nextIndex = index;
    }

    public boolean hasNext() {
      return nextIndex < size;
    }

    public E next() {
      checkForComodification();
      if (!hasNext())
        throw new NoSuchElementException();

      lastReturned = next;
      next = next.next;
      nextIndex++;
      return lastReturned.item;
    }

    public boolean hasPrevious() {
      return nextIndex > 0;
    }

    public E previous() {
      checkForComodification();
      if (!hasPrevious())
        throw new NoSuchElementException();

      lastReturned = next = (next == null) ? last : next.prev;
      nextIndex--;
      return lastReturned.item;
    }

    public int nextIndex() {
      return nextIndex;
    }

    public int previousIndex() {
      return nextIndex - 1;
    }

    public void remove() {
      checkForComodification();
      if (lastReturned == null)
        throw new IllegalStateException();

      Node<E> lastNext = lastReturned.next;
      unlink(lastReturned);
      if (next == lastReturned)
        next = lastNext;
      else
        nextIndex--;
      lastReturned = null;
      expectedModCount++;
    }

    public void set(E e) {
      if (lastReturned == null)
        throw new IllegalStateException();
      checkForComodification();
      lastReturned.item = e;
    }

    public void add(E e) {
      checkForComodification();
      lastReturned = null;
      if (next == null)
        linkLast(e);
      else
        linkBefore(e, next);
      nextIndex++;
      expectedModCount++;
    }

    public void forEachRemaining(Consumer<? super E> action) {
      Objects.requireNonNull(action);
      while (modCount == expectedModCount && nextIndex < size) {
        action.accept(next.item);
        lastReturned = next;
        next = next.next;
        nextIndex++;
      }
      checkForComodification();
    }

    final void checkForComodification() {
      if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
    }
  }

LinkedList的迭代器類的實現(xiàn)邏輯與ArrayList大致相近但是其訪問元素的方式由原來的下標(biāo)變?yōu)?"指針"(Java強引用)

Set

通過看Java源碼可以知道Set全家桶基本上都包含了Map,相當(dāng)于是一種組合的方式

HashSet

構(gòu)造方法

HashSet有多個構(gòu)造方法但都是初始化一個HashMap或其子類

/**
   * Constructs a new, empty set; the backing {@code HashMap} instance has
   * default initial capacity (16) and load factor (0.75).
   */
  public HashSet() {
    map = new HashMap<>();
  }

  /**
   * Constructs a new set containing the elements in the specified
   * collection. The {@code HashMap} is created with default load factor
   * (0.75) and an initial capacity sufficient to contain the elements in
   * the specified collection.
   *
   * @param c the collection whose elements are to be placed into this set
   * @throws NullPointerException if the specified collection is null
   */
  public HashSet(Collection<? extends E> c) {
    map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
    addAll(c);
  }

  /**
   * Constructs a new, empty set; the backing {@code HashMap} instance has
   * the specified initial capacity and the specified load factor.
   *
   * @param   initialCapacity  the initial capacity of the hash map
   * @param   loadFactor    the load factor of the hash map
   * @throws   IllegalArgumentException if the initial capacity is less
   *       than zero, or if the load factor is nonpositive
   */
  public HashSet(int initialCapacity, float loadFactor) {
    map = new HashMap<>(initialCapacity, loadFactor);
  }

  /**
   * Constructs a new, empty set; the backing {@code HashMap} instance has
   * the specified initial capacity and default load factor (0.75).
   *
   * @param   initialCapacity  the initial capacity of the hash table
   * @throws   IllegalArgumentException if the initial capacity is less
   *       than zero
   */
  public HashSet(int initialCapacity) {
    map = new HashMap<>(initialCapacity);
  }

  /**
   * Constructs a new, empty linked hash set. (This package private
   * constructor is only used by LinkedHashSet.) The backing
   * HashMap instance is a LinkedHashMap with the specified initial
   * capacity and the specified load factor.
   *
   * @param   initialCapacity  the initial capacity of the hash map
   * @param   loadFactor    the load factor of the hash map
   * @param   dummy       ignored (distinguishes this
   *       constructor from other int, float constructor.)
   * @throws   IllegalArgumentException if the initial capacity is less
   *       than zero, or if the load factor is nonpositive
   */
  HashSet(int initialCapacity, float loadFactor, boolean dummy) {
    map = new LinkedHashMap<>(initialCapacity, loadFactor);
  }

iterator方法

該接口在HashSet中的實現(xiàn)相當(dāng)?shù)暮唵?可以看到iterator返回了keySet().iterator()

public Iterator<E> iterator() {
    return map.keySet().iterator();
  }

HashMap的KeySet

從這一處代碼可以看到iterator()返回了對象 KeyIterator

final class KeySet extends AbstractSet<K> {
    public final int size()         { return size; }
    public final void clear()        { HashMap.this.clear(); }
    public final Iterator<K> iterator()   { return new KeyIterator(); }
    public final boolean contains(Object o) { return containsKey(o); }
    public final boolean remove(Object key) {
      return removeNode(hash(key), key, null, false, true) != null;
    }
    public final Spliterator<K> spliterator() {
      return new KeySpliterator<>(HashMap.this, 0, -1, 0, 0);
    }
    public final void forEach(Consumer<? super K> action) {
      Node<K,V>[] tab;
      if (action == null)
        throw new NullPointerException();
      if (size > 0 && (tab = table) != null) {
        int mc = modCount;
        for (Node<K,V> e : tab) {
          for (; e != null; e = e.next)
            action.accept(e.key);
        }
        if (modCount != mc)
          throw new ConcurrentModificationException();
      }
    }
  }

HashMap的KeyIterator

KeyIterator是HashIterator一個子類在此一并展示了,這個類從字段結(jié)構(gòu)上跟LinkedList的ListItr還是很像的

獲取next的機制 Node<K,V> 內(nèi)部本身包含一個next引用當(dāng)HashIterator或其子類對象調(diào)用方法nextNode時,若該引用非空者優(yōu)先返回該引用指向的對象,否則掩蓋引用的index在HashMap內(nèi)部的 Node<K,V> 數(shù)組table中向后找, 直到找到一個不為空的引用,或者到table結(jié)束也沒有找到, 那么此時返回空引用

abstract class HashIterator {
    Node<K,V> next;    // next entry to return
    Node<K,V> current;   // current entry
    int expectedModCount; // for fast-fail
    int index;       // current slot

    HashIterator() {
      expectedModCount = modCount;
      Node<K,V>[] t = table;
      current = next = null;
      index = 0;
      if (t != null && size > 0) { // advance to first entry
        do {} while (index < t.length && (next = t[index++]) == null);
      }
    }

    public final boolean hasNext() {
      return next != null;
    }

    final Node<K,V> nextNode() {
      Node<K,V>[] t;
      Node<K,V> e = next;
      if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
      if (e == null)
        throw new NoSuchElementException();
      if ((next = (current = e).next) == null && (t = table) != null) {
        do {} while (index < t.length && (next = t[index++]) == null);
      }
      return e;
    }

    public final void remove() {
      Node<K,V> p = current;
      if (p == null)
        throw new IllegalStateException();
      if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
      current = null;
      removeNode(p.hash, p.key, null, false, false);
      expectedModCount = modCount;
    }
  }

  final class KeyIterator extends HashIterator
    implements Iterator<K> {
    public final K next() { return nextNode().key; }
  }

以上就是怎么在Java中利用Set&List實現(xiàn)迭代器,小編相信有部分知識點可能是我們?nèi)粘9ぷ鲿姷交蛴玫降?。希望你能通過這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI