Java列表最佳实践

3

我需要一些容器来存储元素,这样,如果我尝试获取size()+i个元素,我将获得第i个元素。或者使用迭代器,在它尝试获取最后一个元素后从容器的开头开始?在这两种情况下,最佳实践是什么?我的意思是性能和易用性。


1
我认为这被称为“环形缓冲区”或“循环缓冲区”。不确定Java是否有,但C++在Boost库中有一个。 - Kerrek SB
你确定使用这样的数据结构是个好主意吗?你需要它做什么? - toto2
我有一个DodgerAI类,它处理游戏中某个英雄的人工智能。它有一个英雄索引字段和代表游戏逻辑的字段。在AI中有许多情况(DodgerAI方法),需要分析除了由AI控制的英雄之外的所有英雄。这就是为什么我想使用某种“环”的原因。 - Deepscorn
4个回答

9
您可以创建一个简单的 ArrayList<T> 子类,并按如下方式覆盖 get(int n) 方法:
public T get(int n)
{
    return super.get(n % this.size());
}

关于迭代器,你需要实现自己的迭代器,这并不难。

编辑:

假设你的新类名为RingList,这里是一个示例RingIterator(未经测试):

public class RingIterator<T> implements Iterator<T>
{
    private int cur = 0;
    private RingList<T> coll = null;

    protected RingIterator(RingList<T> coll) { this.coll = coll; }
    public boolean hasNext() { return size() > 0; }
    public T next() 
    { 
        if (!hasNext()) 
            throw new NoSuchElementException();
        int i=cur++; 
        cur=cur%size(); 
        return coll.get(i);
    }
    public void remove() { throw new UnsupportedOperationException(); }
}

你需要在 RingList<T> 中覆盖 iterator() 方法,如下所示:

public Iterator<T> iterator()
{
    return new RingIterator(this);
}

所有方法(remove等)不应该都使用相同的索引而不仅仅是get吗?小错误:当cur换行时... - dacwe
@dacwe:当然可以。我可以说“留给读者作为练习” :-) - Jim Garrison
1
:-) 很好,现在只剩一个空列表的情况了,但我们就让它空着吧;-) - dacwe
看起来空列表状态在上面的代码中也已经被实现了,所以它没有被遗漏 :)。 - Maarten Bodewes

2

对于第一部分,只需请求n%list.size()即可?

对于迭代器部分,创建一个包装迭代器的类,并且当next()返回null时,只需重置迭代器即可。


1

谢谢大家,这就是我创建的内容:

public class RingIterator<E> {
private List<E> _lst;
private ListIterator<E> _lstIter;

public RingIterator(ListIterator<E> iter, List<E> lst) {
    super();
    _lstIter = iter;
    _lst = lst;
}

public E next() {
    if(!_lstIter.hasNext())
        _lstIter = _lst.listIterator();
    return _lstIter.next();
}

public E previous() {
    if(!_lstIter.hasPrevious())
        _lstIter = _lst.listIterator(_lst.size());
    return _lstIter.previous();
}

}

然后获取方法:

/*
 * Returns ring iterator,
 * use it with 'ParentClass' type.
 */
public RingIterator<SubClass> getRingIter(int i) {
    return new RingIterator(_subs.listIterator(i),_subs);
}

我使用它:

RingIterator<SubClass> ri = _logic.getRingIter(1);
ParentClass ai = ri.next();

我想让仅 ParentClass 类型(而不是 SubClass)通过 getRingIter 可用,但我不知道如何在不创建 List 的情况下完成它 - 转换 List。


0

扩展ArrayList类并按照您喜欢的方式实现get(Integer)方法。我认为这是“最佳实践”。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接