将List或单个List Items作为Java中的方法参数传递是否更有效?

时间:2016-10-19 00:45:23

标签: java list methods parameter-passing pass-by-value

假设我有一个包含100个字符串的列表。以下两种方法在性能(或任何其他差异)方面是否存在差异

1

List<String> myList = Arrays.asList("s1", "s2", "s3"....."s100");        
foo(myList);

private void foo(List<String> myList) {
    // logic to choose 2 strings from the list
    //do something with -- str1 and str2
}

2

List<String> myList = Arrays.asList("s1", "s2", "s3"....."s100");    
// logic to choose 2 strings from the list
foo(str1, str2);

private void foo(String myStr1, String myStr2) {
    //do something with -- myStr1 and myStr2
}

由于Java传递了List或单个字符串的引用(作为值),我假设这些参数只包含(副本)引用/地址。所以我倾向于通过整个列表。

以上将是一种实用方法,我想让“逻辑”从列表中选择2个字符串&#39;在foo方法中,呼叫者在呼叫之前不必重复该逻辑;但我担心发送一个大型列表作为参数。

感谢您的帮助。

** 修改 :** 是的我正在寻找性能问题。

List<String>可能不是正确的例子。可以将其视为Map<String,Long>(城市,温度)。而且逻辑将是总是选择芝加哥和洛杉矶,foo将根据温度进行操作。请注意,此逻辑将始终相同,并且调用者只会在方法#2中重复相同的代码。

3 个答案:

答案 0 :(得分:4)

我建议您忽略性能方面的潜在差异(在这种情况下可以忽略不计),并完全关注代码的清晰度。换句话说,问题不是哪个更有效,而是更好地反映了你所调用的方法的意图。如果foo是一个自然会期望两个参数(例如storeFullName)的方法,那么它应该传递两个参数。如果它自然希望从列表中选择两个值(例如printTwoLongestStrings)那么它应该采用集合。

您也可以考虑给每个方法single responsibility的原则。在这种情况下,使用单独的方法来选择这两个值并对它们执行某些操作可能是有意义的:

Pair<String, String> longestPair = getTwoLongestStrings(list);
printStrings(longestPair);

**编辑**

您的问题已澄清您专注于性能,并且您提供了有关用例的更多详细信息。具体来说,您要问的是将一个列表或两个值传递给方法时的性能是否存在差异。是,有一点不同。我运行了一个试验,用两个String参数和一个列表调用一个空函数100亿次。列表调用花费了24秒,单独的参数调用花费了13秒。其他物理硬件可能会显示不同的结果。 JVM优化也不能使其成为公平的测试。

public class PerfTest {

    public static void main(String[] args) {
        List<String> list = Arrays.asList("a", "b");
        long time1 = System.currentTimeMillis();
        for (long i = 0; i < 1E10; i++) {
            func1("a", "b");
        }
        long time2 = System.currentTimeMillis();
        for (long i = 0; i < 1E10; i++) {
            func2(list);
        }
        System.out.println((time2 - time1) + "/" + (System.currentTimeMillis() - time2));
    }

    private static void func1(String s1, String s2) { }
    private static void func2(List<String> sl) { }
}

然而,我上面的答案仍然存在:如果你要调用一个功能100亿次,那么它可能值得优化,但更好的做法是从关注清晰度开始,然后使用分析来集中代码调优工作,如果这样做是必需的。

答案 1 :(得分:1)

我想你是在询问是否通过引用传递了List参数。它是。在编译的机器代码中,对于list参数,只有一个指向列表对象实例的指针将被传递给该函数。没有理由担心将大型列表作为参数。

答案 2 :(得分:0)

如果方法对列表本身感兴趣而不仅仅是其项目,我推荐仅使用List作为参数。它计划修改它。

对于其他情况,如果你有一个固定数量的参数,你应该让每个参数都是它自己的参数。但是你的案例表明你有不同数量的参数。为此你也可以使用varargs:

private void foo(String... strings) {
    // `strings` is an array now
}

这样做的好处是调用者可以选择使用单个对象或数组来调用你的函数:

foo("Hello", "World");

或者

String[] strings = new String[]{"Hello", "World"};
foo(strings);

甚至是这样:

List<String> strings = ...;
foo(strings.toArray(new String[0]));

如果您担心将列表转换为数组,请坚持传递列表本身。