Java 有没有办法访问LinkedHashMap的内部节点?

Java 有没有办法访问LinkedHashMap的内部节点?,java,linkedhashmap,Java,Linkedhashmap,我希望他们为一个集合做一个自定义迭代器 (elem)中的ListIterator扩展了实现并添加了一些façade方法我现在有了一个解决方案,它不使用扩展或反射(或者实际上是LinkedHashMap) 你觉得怎么样 package i3.util; import java.util.AbstractSet; import java.util.Collection; import java.util.ConcurrentModificationException; import java.ut

我希望他们为一个集合做一个自定义迭代器


(elem)中的ListIterator扩展了实现并添加了一些façade方法

我现在有了一个解决方案,它不使用扩展或反射(或者实际上是LinkedHashMap)

你觉得怎么样

package i3.util;

import java.util.AbstractSet;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.Map;
import java.util.NoSuchElementException;

/**
 * This class is a like LinkedHashSet (insertion order) but it allows querying
 * the relative position of a element and has a ListIterator that can set and
 * insert anywhere.
 *
 * Warning: the iterator can change the order of the set by moving elements when
 * setting or adding. Elements that already exist are not ignored, but moved the
 * requested place. This changes iteration order
 *
 *
 * The iterators of this class are fail fast and will throw a
 * ConcurrentModificationException if their iterator are used with intervening
 * main class (or other iterators) mutative calls
 *
 * @author i30817 <i30817@gmail.com>
*/
public class LinkedSet<E> extends AbstractSet<E> {

//It holds the linked list
private Map<E, Node> m = new HashMap<E, Node>();
//head of that
protected Node head = new Node();
//this is copied to the map value in increments of iteratorAddStep on set.add
//(which only adds to the end, by insertion indexing)
private int monotonicallyIncreasing = 0;
//iterator add step may change when doing rebuilds of the 'space' between elements
//for the before/after functions on LinkedKeyIterator.add
private int iteratorAddStep = 10;
//for fail fast iterators
private int modCount;

/**
 * Start iterating from elem (inclusive)
 *
 *
 * @throws NoSuchElementException if E not part of the set
 * @param elem a element of the set
 * @return a ListIterator - doesn't support nextIndex() or previousIndex()
 */
public ListIterator<E> from(E elem) {
    Node e = m.get(elem);
    if (e == null) {
        throw new NoSuchElementException("the given element isn't part of the set");
    }
    return new LinkedKeyIterator(e);
}

@Override
public ListIterator<E> iterator() {
    return new LinkedKeyIterator();
}

/**
 * Returns true if the value target was added before (exclusive) limitElem
 * in insertion order.
 *
 * If target or limit are not present on the set this method returns false
 *
 * @param limitElem a E that may be a element of the set or not.
 * @return if target was added before limit (can be reset by removing and
 * re-adding the target, that changes iteration order).
 */
public boolean containsBefore(E target, E limitElem) {
    if (isEmpty()) {
        return false;
    }

    Integer targetN = m.get(target).relativeLocation;
    Integer highN = m.get(limitElem).relativeLocation;
    return targetN != null && highN != null && targetN < highN;
}

/**
 * Returns true if the value target was added after (exclusive) previousElem
 * in insertion order.
 *
 * If target or previous are not present on the set this method returns
 * false
 *
 * @param previousElem a E that may be a element of the set or not.
 * @return if target was added before previous (can be reset by removing and
 * re-adding the target, that changes iteration order).
 */
public boolean containsAfter(E target, E previousElem) {
    if (isEmpty()) {
        return false;
    }

    Integer targetN = m.get(target).relativeLocation;
    Integer low = m.get(previousElem).relativeLocation;
    return targetN != null && low != null && low < targetN;
}

@Override
public boolean add(E e) {
    if (!m.containsKey(e)) {
        Node n = new Node(e, monotonicallyIncreasing);
        monotonicallyIncreasing += iteratorAddStep;
        n.addBefore(head);//insertion order
        m.put(e, n);
        return true;
    }
    return false;
}

@Override
public int size() {
    return m.size();
}

@Override
public boolean isEmpty() {
    return m.isEmpty();
}

@Override
public boolean contains(Object o) {
    return m.containsKey(o);
}

@Override
public Object[] toArray() {
    Object[] result = new Object[size()];
    int i = 0;
    for (E e : this) {
        result[i++] = e;
    }
    return result;
}

@Override
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
    int size = size();
    if (a.length < size) {
        a = (T[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);
    }
    int i = 0;
    Object[] result = a;
    for (E e : this) {
        result[i++] = e;
    }
    if (a.length > size) {
        //peculiar toArray contract where it doesn't care about the rest
        a[size] = null;
    }
    return a;
}

@Override
public boolean remove(Object o) {
    Node n = m.remove(o);
    if (n != null) {
        n.remove();
        return true;
    }
    return false;
}

@Override
public boolean addAll(Collection<? extends E> c) {
    boolean changed = false;
    for (E e : c) {
        changed |= add(e);
    }
    return changed;
}

@Override
public boolean containsAll(Collection<?> c) {
    boolean all = true;
    for (Object e : c) {
        all &= m.containsKey(e);
    }
    return all;
}

@Override
public boolean retainAll(Collection<?> c) {
    boolean changed = false;
    Iterator<E> it = iterator();
    while (it.hasNext()) {
        E k = it.next();
        if (!c.contains(k)) {
            it.remove();
            changed = true;
        }
    }
    return changed;
}

@Override
public void clear() {
    modCount++;
    head.after = head.before = head;
    m.clear();
}

@Override
public String toString() {
    return  m.keySet().toString();
}

//linkedlist node class
protected final class Node {

    Node before, after;
    int relativeLocation;
    //needed for map removal during iteration
    E key;

    private void remove() {
        before.after = after;
        after.before = before;
        modCount++;
    }

    private void addBefore(Node existingEntry) {
        after = existingEntry;
        before = existingEntry.before;
        before.after = this;
        after.before = this;
        modCount++;
    }

    //head const
    public Node() {
        after = before = this;
        relativeLocation = 0;
    }

    public Node(E key, int value) {
        this.key = key;
        this.relativeLocation = value;
    }
}

protected class LinkedKeyIterator implements ListIterator<E> {

    Node nextEntry;
    Node lastReturned;
    int expectedModCount = modCount;

    public LinkedKeyIterator() {
        nextEntry = head.after;
    }

    public LinkedKeyIterator(Node startAt) {
        nextEntry = startAt;
    }

    public boolean hasPrevious() {
        return nextEntry.before != head;
    }

    public boolean hasNext() {
        return nextEntry != head;
    }

    public E next() {
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        if (nextEntry == head) {
            throw new NoSuchElementException();
        }

        Node e = lastReturned = nextEntry;
        nextEntry = e.after;
        return e.key;
    }

    public E previous() {
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        if (nextEntry.before == head) {
            throw new NoSuchElementException();
        }

        Node e = lastReturned = nextEntry.before;
        nextEntry = e;
        return e.key;
    }

    public void remove() {
        if (lastReturned == null) {
            throw new IllegalStateException();
        }
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        m.remove(lastReturned.key);
        nextEntry = lastReturned.after;
        lastReturned.remove();
        lastReturned = null;
        expectedModCount = modCount;
    }

    @Override
    public void set(E e) {
        if (lastReturned == null) {
            throw new IllegalStateException();
        }
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        if (lastReturned.key.equals(e)) {
            return;
        }
        //remove mapping for key since we are changing it
        m.remove(lastReturned.key);
        //put in the new one
        lastReturned.key = e;
        Node previousKeyOwner = m.put(e, lastReturned);
        if (previousKeyOwner != null) {
            //as it is a list mutation call, guard against stale iterator
            if(nextEntry == previousKeyOwner){
                nextEntry = nextEntry.after;
            }
            previousKeyOwner.remove();
        }
        //from m.remove and m.put, may help with 2 concurrent iterators on this instance
        //this method may not change modCount if previousKeyOwner is null
        expectedModCount = ++modCount;
    }

    @Override
    public void add(E e) {
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        //calculate a good relative location, updating subsequent ones if needed
        int candidateLoc = nextEntry.before.relativeLocation + 1;
        //opsss, it's full
        if (candidateLoc == nextEntry.relativeLocation) {
            iteratorAddStep *= 1.6;
            for (Node current = nextEntry; current != head; current = current.after) {
                current.relativeLocation = current.relativeLocation + iteratorAddStep;
            }
        }

        Node n = m.get(e);
        if (n == null) {
            n = new Node(e, candidateLoc);
            m.put(e, n);
        } else {
            n.relativeLocation = candidateLoc;
            //as it is a list mutation call, guard against stale iterator
            if(nextEntry == n){
                nextEntry = nextEntry.after;
            }
            n.remove();
        }
        n.addBefore(nextEntry);
        expectedModCount = modCount;//add before changes modCount
    }

    @Override
    public int nextIndex() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public int previousIndex() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}
}
包i3.util;
导入java.util.AbstractSet;
导入java.util.Collection;
导入java.util.ConcurrentModificationException;
导入java.util.HashMap;
导入java.util.Iterator;
导入java.util.ListIterator;
导入java.util.Map;
导入java.util.NoSuchElementException;
/**
*此类类似于LinkedHashSet(插入顺序),但它允许查询
*元素的相对位置,并具有可以设置和
*插入任意位置。
*
*警告:迭代器可以通过在下列情况下移动元素来更改集合的顺序:
*设置或添加。不会忽略已存在的元素,而是将其移动到
*请求地点。这会改变迭代顺序
*
*
*该类的迭代器故障很快,将抛出
*ConcurrentModificationException,如果其迭代器用于干预
*主类(或其他迭代器)可变调用
*
*@author i30817
*/
公共类LinkedSet扩展了抽象集{
//它保存链接列表
私有映射m=新的HashMap();
//头儿
受保护的节点头=新节点();
//这将在set.add上以迭代器ADDSTEP的增量复制到映射值
//(仅通过插入索引添加到末尾)
私有int单调递增=0;
//在重建元素之间的“空间”时,迭代器添加步骤可能会更改
//对于LinkedKeyIterator.add上的before/after函数
私有int迭代器adstep=10;
//对于失败快速迭代器
私有int modCount;
/**
*从元素开始迭代(包括元素)
*
*
*@如果E不是集合的一部分,则抛出NoSuchElementException
*@param elem集合中的一个元素
*@返回ListIterator-不支持nextIndex()或previousIndex()
*/
来自(E元素)的公共列表迭代器{
节点e=m.get(elem);
如果(e==null){
抛出新的NoSuchElementException(“给定元素不是集合的一部分”);
}
返回新的LinkedKeyIterator(e);
}
@凌驾
公共列表迭代器迭代器(){
返回新的LinkedKeyIterator();
}
/**
*如果在(独占)limitElem之前添加了值目标,则返回true
*按插入顺序。
*
*如果集合上不存在目标或限制,则此方法返回false
*
*@param limitElem可能是集合中的元素,也可能不是。
*@return如果目标是在限制之前添加的(可以通过移除和
*重新添加目标,这会改变迭代顺序)。
*/
公共布尔值包含在(E目标、E限制元素)之前{
if(isEmpty()){
返回false;
}
整数targetN=m.get(target).relativeLocation;
整数highN=m.get(limitElem).相对位置;
返回targetN!=null&&highN!=null&&targetN尺寸){
//这是一个奇怪的阵列合同,它不关心其他的
a[size]=null;
}
返回a;
}
@凌驾
公共布尔删除(对象o){
节点n=m.remove(o);
如果(n!=null){
n、 删除();
返回true;
}
返回false;
}
@凌驾
公共布尔addAll(集合c){
布尔值all=true;
用于(对象e:c){
全部&=m.CONTANSKEY(e);
}
全部归还;
}
@凌驾
公共布尔保留(集合c){
布尔值=假;
迭代器it=迭代器();
while(it.hasNext()){
ek=it.next();
如果(!c.包含(k)){
it.remove();
更改=正确;
}
}
回报发生变化;
}
@凌驾
公共空间清除(){
modCount++;
head.after=head.before=head;
m、 清除();
}
@凌驾
公共字符串toString(){
返回m.keySet().toString();
}
//linkedlist节点类
受保护的最终类节点{
节点前、后;
国际关系定位;
//需要在迭代期间删除映射
E键;
私有无效删除(){
before.after=之后;
before=before;
modCount++;
}
私有void addBefore(节点existingEntry){
之后=现有条目;
before=existingEntry.before;
在此之前。之后=此;
之后。之前=这个;
modCount++;
}
//总目c
public class Map<K, V> extends HashMap<K, V> {

    public Set<K, V> entrySet() {
        return new HashSet<K, V>(super.entrySet()) {
            public Iterator<Map.Entry<K, V>> iterator () {
                 return // some custom implementation
            }
        };
    }

    // similar for keySet() if you wish
}