性能与内存列表

Performance vs memory Lists

什么会更好?

假设我们有一个 class mainClass 有一个 List<BigClass>List<Foo>foos...

Foo本身就有一个List<Boo>

如果目标是能够获得 foos 的所有元素的所有 Boo。 如果用户要将新的 Foo 插入 foos,那么在 BigClass 中保留另一个 List<Boo> 并插入相应的 Boo 元素会更好吗?

或者每次用户请求此列表时从“BigClass”中生成此总 Boo 列表会更好吗?

这里的主要问题是,您必须在这里选择性能还是内存?

PS。 抱歉标题太笼统,不太清楚如何命名这个问题:/

您可以通过一个实现同时拥有这两种行为。只需在 mainClass 中创建您自己的 List 实现(可能是一个名为 FooList 的内部 class,或者甚至是一个匿名内部 class)。使 FooList 的方法透明地将所有单独的 Foo 列表呈现为单个列表。例如,FooList.iterator() 的实现将透明地依次在每个单独的 Foo 列表上实例化一个迭代器,因此它看起来像是在遍历单个大列表。

如果您既需要获取所有 Boos 又需要将 Boos 分组(即属于某些 FooBoos),那么我最好的办法是 return 查看 BigClass 中所有 Boo,无论哪个 Foo他们属于。

为此,您可以使用 Google Guava Iterables or Java 8 Stream.flatMap(),具体取决于您的 Java 版本。

与Google番石榴:

class BigClass {

    List<Foo> foos = new LinkedList<Foo>();

    public Iterable<Boo> allBoos() {
        return Iterables.concat(this.foos);
    }
}

class Boo {
    final int a;

    Boo(int a) {
        this.a = a;
    }

    @Override
    public String toString() {
        return String.valueOf(this.a);
    }
}

class Foo
    implements Iterable<Boo> {

    List<Boo> boos = new LinkedList<Boo>();

    @Override
    public Iterator<Boo> iterator() {
        return this.boos.iterator();
    }
}

public class Sample {
    public static void main(String[] args) {

        Boo b1 = new Boo(1);
        Boo b3 = new Boo(3);
        Boo b5 = new Boo(5);

        Boo b2 = new Boo(2);
        Boo b4 = new Boo(4);
        Boo b6 = new Boo(6);

        Foo odd = new Foo();
        odd.boos.addAll(Arrays.asList(b1, b3, b5));

        Foo even = new Foo();
        even.boos.addAll(Arrays.asList(b2, b4, b6));

        BigClass b = new BigClass();
        b.foos.add(odd);
        b.foos.add(even);

        System.out.println(b.allBoos()); // [1, 3, 5, 2, 4, 6]
    }
}

这种方法最好的地方在于 Iterable Guava returns 是 lazy,这意味着不会创建和填充新的集合或列表与任何元素。相反,returned Iterable 是一个视图,其 Iterator 消耗第一个 Iterable 的元素,并且在耗尽时,"jumps" 到下一个 Iterable 并消耗它的元素,并且 "jumps" 到下一个,依此类推,直到最后一个 Iterable 的最后一个元素被消耗。

与Java 8:

class BigClass {

    List<Foo> foos = new LinkedList<Foo>();

    public Iterable<Boo> allBoos() {
        Stream<Boo> s = this.foos.stream().flatMap(
            f -> f.getBoos().stream());
        return s::iterator;
    }
}

class Boo {
    final int a;

    Boo(int a) {
        this.a = a;
    }

    @Override
    public String toString() {
        return String.valueOf(this.a);
    }
}

class Foo {

    List<Boo> boos = new LinkedList<Boo>();

    public List<Boo> getBoos() {
        return this.boos;
    }
}

public class Sample {
    public static void main(String[] args) {

        Boo b1 = new Boo(1);
        Boo b3 = new Boo(3);
        Boo b5 = new Boo(5);

        Boo b2 = new Boo(2);
        Boo b4 = new Boo(4);
        Boo b6 = new Boo(6);

        Foo odd = new Foo();
        odd.boos.addAll(Arrays.asList(b1, b3, b5));

        Foo even = new Foo();
        even.boos.addAll(Arrays.asList(b2, b4, b6));

        BigClass b = new BigClass();
        b.foos.add(odd);
        b.foos.add(even);

        List<Boo> list = new ArrayList<>();
        b.allBoos().forEach(boo -> list.add(boo));

        System.out.println(list); // [1, 3, 5, 2, 4, 6]
    }
}

关于懒惰的相同注意事项也适用于此。