Search code examples
javalistmethodsparameter-passingpass-by-value

Is it more efficient to pass a List or individual List Items as method arguments in Java?


Assuming I have a list of 100 strings. Is there a difference between the following two approaches in performance (or any other difference)

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
}

Since Java passes the reference(as values) of the List or individual Strings I am assuming those arguments will just hold (copies of) references/addresses. So I am leaning towards passing the entire list.

The above will be a utility method and I want to put the 'logic to choose 2 strings from the list' inside the foo method so callers don't have to repeat that logic before calling; but I am concerned about sending a large list as argument.

Thanks for help.

** Edit :** Yes I am looking for Performance concerns.

And List<String> probably wasn't the correct example. Think of it as a Map<String,Long> (City,Temperature). And the logic will be to always choose Chicago and LA and foo will operate on the temperatures. Note that this logic will always be the same and callers would just repeat the same code in approach #2.


Solution

  • I recommend you ignore potential difference in performance (which would be negligible in this case) and focus entirely on clarity of your code. In other words, the question is not which is more efficient but which better reflects the intention of the method you are calling. If foo is a method which would naturally expect two arguments (such as storeFullName) then it should be passed two arguments. If it would naturally expect to select two values from a list (such as printTwoLongestStrings) then it should take a collection.

    You might also consider the principle of giving each method a single responsibility. In that case it might make sense to have separate methods for selecting the two values and doing something with them:

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

    ** Edit **

    Your question has clarified that you are focused specifically on performance and you provided more detail of your use case. Specifically you are asking if there is a difference in performance in passing a list or two values to a method. Yes there is a difference. I ran a trial calling an empty function 10 billion times with two String arguments and with a list. The list call took 24 secs and the separate argument call took 13 secs. It's likely that other physical hardware will show different results. It's also possible that JVM optimisation is not making this a fair test.

    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) { }
    }
    

    However my answer above still stands: if you are calling a function 10 billion times then it might be worth optimising but it is much better practice to start with a focus on clarity and then use profiling to focus code-tuning effort if that is required.