Gadam
Gadam

Reputation: 3024

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.

Upvotes: 1

Views: 1708

Answers (3)

sprinter
sprinter

Reputation: 27976

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.

Upvotes: 5

Sean F
Sean F

Reputation: 4605

I think you are asking if a List argument is passed by reference. It is. In the compiled machine code, for the list argument just a single pointer to the list object instance will be passed to the function. There is no reason to be concerned about having a large list as an argument.

Upvotes: 2

Felk
Felk

Reputation: 8224

I recommend only using a List as an argument if the method is interested in the list itself and not only its items, e.g. it plans on modifying it.

For the other cases, if you have a fixed number of arguments, you should have each argument be it's own parameter. But your case suggested that you have a variable number of arguments. For this you could also use varargs:

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

This has the advantage that the caller can choose to either invoke your function using single objects, or an array:

foo("Hello", "World");

or this

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

or even this:

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

If you have concerns about turning your list into an array, stick with passing the list itself.

Upvotes: 1

Related Questions