Java 在ArrayList中创建元素的临时副本以减少计算时间和复杂性是否更好?

Java 在ArrayList中创建元素的临时副本以减少计算时间和复杂性是否更好?,java,arraylist,Java,Arraylist,我有一个包含对象卡的ArrayList,它有int-value、String-symbol和String-image属性,属于getter ArrayList<card> cardDeck = new ArrayList<>(); 第二种解决方案: for(int i = 0; i < cardDeck.size(); i++){ card temp = cardDeck.get(i); System.out.println((i + 1) + "

我有一个包含对象卡的ArrayList,它有int-value、String-symbol和String-image属性,属于getter

ArrayList<card> cardDeck = new ArrayList<>();
第二种解决方案:

for(int i = 0; i < cardDeck.size(); i++){
    card temp = cardDeck.get(i);
    System.out.println((i + 1) + ". card:");
    System.out.println(temp.getValue());
    System.out.println(temp.getSymbol());
    System.out.println(temp.getImage());
}
我的问题是,在执行时间或复杂性上是否有任何明显的差异。 首先,在第一种解决方案中,程序每次都必须首先在ArrayList中查找卡片,然后才能打印其信息。在第二种解决方案中,情况并非如此,因为制作了临时副本。 但是再仔细想想,即使在第二种解决方案中,程序仍然需要在每次调用时查找临时卡对象的信息。 感谢任何帮助/想法/建议

使用Java 8

    cardDeck.parallelStream().forEach(card -> {System.out.println(card.getValue());System.out.println(card.getSymbol());System.out.println(card.getImage());});
这并不能保证更好的性能,这取决于可用的CPU内核数量。

使用Java 8

    cardDeck.parallelStream().forEach(card -> {System.out.println(card.getValue());System.out.println(card.getSymbol());System.out.println(card.getImage());});
这并不能保证更好的性能,这取决于可用CPU内核的数量。

所以我们有

3个具有相同索引且不修改数组的数组查找,因此编译器可以在第一个解决方案中对其进行优化 在第一个解决方案中,容易出错的代码如果需要将索引更改为i+1,而忘记在所有3个位置更正代码,会发生什么情况 与:

1第二个解决方案中的数组查找-在不依赖编译器的情况下进行了优化 如果将temp替换为card,则第二种解决方案中的代码可读性更好,如果正确启动类名大写:card card,则可以这样做 数组查找在Java中并不便宜-数组是受保护的边界检查,以防止缓冲区溢出注入漏洞

所以你有两个很好的理由告诉你去使用第二个解决方案

3个具有相同索引且不修改数组的数组查找,因此编译器可以在第一个解决方案中对其进行优化 在第一个解决方案中,容易出错的代码如果需要将索引更改为i+1,而忘记在所有3个位置更正代码,会发生什么情况 与:

1第二个解决方案中的数组查找-在不依赖编译器的情况下进行了优化 如果将temp替换为card,则第二种解决方案中的代码可读性更好,如果正确启动类名大写:card card,则可以这样做 数组查找在Java中并不便宜-数组是受保护的边界检查,以防止缓冲区溢出注入漏洞


因此,有两个很好的理由告诉您使用第二个解决方案。

首先,您有其他解决方案,例如,使用for eatch循环或使用forEatch方法和lambda表达式。 关于速度,在你的程序在普通电脑上运行之前,你不必担心速度,你也不必处理处理器太弱或太低的问题,但在你的情况下,你可以通过使用函数式编程来降低应用程序的复杂度,例如

cardDec.forEatch(card) -> {
    System.out.println(card.getValue());
    System.out.println(card.getSymbol());
    System.out.println(card.getImage());

};

首先,您有其他解决方案,例如,使用for eatch循环或使用forEatch方法和lambda表达式。 关于速度,在你的程序在普通电脑上运行之前,你不必担心速度,你也不必处理处理器太弱或太低的问题,但在你的情况下,你可以通过使用函数式编程来降低应用程序的复杂度,例如

cardDec.forEatch(card) -> {
    System.out.println(card.getValue());
    System.out.println(card.getSymbol());
    System.out.println(card.getImage());

};

彼得已经说过,从编程的角度来看,什么是更好的主意。 我想补充一点,OP询问了复杂性。我将其解释为与卡片组大小相关的渐近时间

答案是,从理论复杂性的角度来看,这两种方法是相同的。每次数组查找都会向所需时间添加一个常数因子。都是开着的,n是牌的数目


另一方面,OP询问复制列表中的元素。只是想说明一下:语句card temp=cardDeck.geti不会导致第i个list元素被复制。temp变量现在只指向运行循环时位于cardDeck第i个位置的元素。

Peter已经说过,从编程角度来看,什么是更好的主意。 我想补充一点,OP询问了复杂性。我将其解释为与卡片组大小相关的渐近时间

答案是,从理论复杂性的角度来看,这两种方法是相同的。每次数组查找都会向所需时间添加一个常数因子。都是开着的,n是牌的数目

另一方面,OP询问复制列表中的元素。只是想说明一下:语句card temp=cardDeck.geti不会导致第i个list元素被复制。temp变量现在只指向运行循环时位于cardDeck第i个位置的元素。

可能int i=0;对于卡c:cardDesk{System.out.printf%d。卡:%s%s%s%n、++i、c.getValue、c.getSymbol、c.getImage;}更好。不过差别很小
,我希望javac或JIT能够优化这一点,但我不确定这一点。我会接受第二个版本。这仅仅是因为它更具可读性。在JIT之后,这两个代码是相同的,唯一的担忧/区别是card变量被声明&在循环之外未经授权地使用。只要n保持不变,就不必担心复杂性…而且你也不必在循环中做太疯狂的事情,比如n^n..为了可读性/性能/兼容性:+1在Alex的评论中。同样,当格式不精确时..但没有问题%n在格式字符串中插入os indep。换行符。可能int i=0;对于卡c:cardDesk{System.out.printf%d。卡:%s%s%s%n、++i、c.getValue、c.getSymbol、c.getImage;}更好。尽管差别很小,但无论什么更易于阅读,我都希望javac或JIT能够对此进行优化,但我不确定这一点。我会接受第二个版本。这仅仅是因为它更具可读性。在JIT之后,这两个代码是相同的,唯一的担忧/区别是card变量被声明&在循环之外未经授权地使用。只要n保持不变,就不必担心复杂性…而且你也不必在循环中做太疯狂的事情,比如n^n..为了可读性/性能/兼容性:+1在Alex的评论中。同样,当格式不精确时..但没有问题%n在格式字符串中插入os indep。我做了一个快速的基准测试,发现编译器没有优化ArrayList访问。甚至对普通数组的访问也没有优化到单个访问。我做了一个快速的基准测试,发现编译器没有优化ArrayList访问。甚至对普通阵列的访问也不能优化为单个访问。