首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >分配免费博弈

分配免费博弈
EN

Stack Overflow用户
提问于 2010-12-07 22:14:38
回答 3查看 348关注 0票数 5

我的代码基本上是无分配的,但是当速度为60fps时,GC大约每30秒运行一次。使用DDMS检查应用程序的分配情况显示,有大量的SimpleListIterator被分配。因为我使用的是Exchanger,所以也会分配一些东西。

SimpleListIterator来自for each loops for (T obj : objs) {}。我的印象是编译器/翻译器会对其进行优化,不会对支持它的类型使用迭代器(我基本上只使用ArrayList),但事实似乎并非如此。

如何避免分配所有这些SimpleListIterators?一种解决方案是切换到常规for循环for (int i = 0; i < size; ++i) {},但我喜欢for each循环:(

另一种方法是扩展ArrayList,它返回一个只分配一次的Iterator

我使用的第三种方法是使用一个静态助手函数,该函数返回一个重用IteratorCollection。我把这样的东西拼凑在一起,但演员阵容感觉非常老套和不安全。但是它应该是线程安全的,因为我使用了ThreadLocal?如下所示:

代码语言:javascript
复制
public class FastIterator {
    private static ThreadLocal<Holder> holders = new ThreadLocal<Holder>();

    public static <T> Iterable<T> get(ArrayList<T> list) {
        Holder cont = holders.get();

        if (cont == null) {
            cont = new Holder();

            cont.collection = new DummyCollection<T>();
            cont.it = new Iterator<T>();

            holders.set(cont);
        }

        Iterator<T> it = (Iterator<T>) cont.it;
        DummyCollection<T> collection = (DummyCollection<T>) cont.collection;

        it.setList(list);
        collection.setIterator(it);

        return collection;
    }

    private FastIterator() {}

    private static class Holder {
        public DummyCollection<?> collection;
        public Iterator<?> it;
    }

    private static class DummyCollection<T> implements Iterable {
        private Iterator<?> it;

        @Override
        public java.util.Iterator<T> iterator() {
            return (java.util.Iterator<T>) it;
        }

        public void setIterator(Iterator<?> it) {
            this.it = it;
        }
    }

    private static class Iterator<T> implements java.util.Iterator<T> {
        private ArrayList<T> list;
        private int size;
        private int i;

        @Override
        public boolean hasNext() {
            return i < size;
        }

        @Override
        public T next() {
            return list.get(i++);
        }

        @Override
        public void remove() {

        }

        public void setList(ArrayList<T> list) {
            this.list = list;
            size = list.size();
            i = 0;
        }

        private Iterator() {}
    }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-12-07 22:18:31

你不应该在Android游戏中使用for each。我认为这个official video也谈到了这一点。

票数 4
EN

Stack Overflow用户

发布于 2010-12-07 22:19:30

也许最好的方法是使用装饰器设计。创建一个类,该类接受构造函数中的一个集合,并通过调用包装的类并重用返回的迭代器来实现Iterable接口。

票数 2
EN

Stack Overflow用户

发布于 2010-12-08 03:54:33

避免分配迭代器的另外两种方法。首先是使用回调习惯用法:

代码语言:javascript
复制
public interface Handler<T> {
  void handle(T element);
}

public interface Handleable<T> {
  void handleAll(Handler<T> handler);
}

public class HandleableList<T> extends ArrayList<T> implements Handleable<T> {
  public void handleAll(Handler<T> handler) {
    for (int i = 0; i < size(); ++i) {
      handler.handle(get(i));
    }
  }
}

这种方法仍然需要一个Handler实例来接收回调,但是当您尝试访问多个列表的元素时,这绝对可以减少分配。

第二种方法是使用光标习惯用法:

代码语言:javascript
复制
public interface Cursor<T> {
  void reset();
  boolean next();
  T current();
}

public class CursoredList<T> extends ArrayList<T> implements Cursor<T> {
  private int _index = -1;

  public void reset() {
    _index = -1;
  }

  public boolean next() {
    return ++_index >= size();
  }

  public T current() {
    return get(_index);
  }
}

当然,这与在ArrayList的子类型上实现Iterable和Iterator是相同的,但这清楚地将光标位置显示为集合本身的状态。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4377533

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档