Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a parameter I can use in Java that works with all for-each loops?

Suppose I've got a method that accepts an array and processes each element in it using Java's built in for-each loop, like this:

public static void myFun(SomeClass[] arr) {
    for (SomeClass sc : arr) {
        // Stuff is processed here
    }
}

This works just fine, but now I want to be able to pass the same method a List<SomeClass> instead. Am I destined to use Collection.toArray(T []), or is there a parameter I can use for myFun() that accepts any type that can be used in a for-each construct?

To clarify: I want a method signature that will accept any iterable object, be it a primitive array or a Collection. I can very easily write two methods, with one wrapping the other, but I'm just curious if there's a better way.

like image 763
Dan Lew Avatar asked Apr 20 '09 18:04

Dan Lew


2 Answers

I would suggest using Iterable, Collection or List as the parameter type.

IMO, collections should be preferred to reference arrays. If you happen to have an array Arrays.asList does the conversion nicely. Arrays.asList allows gets and sets back through to the array, but obviously not "structural" modifications which would change the array length.

myFun(Arrays.asList(arr));

You may have to use wildcards in extreme/general cases.

public static void myFun(Iterable<? extends SomeClass> somethings) {
    for (SomeClass something : somethings) {
        // something is processed here
    }
}

It is noteworthy that Collections.toArray and Arrays.asList work slightly differently. asList keeps the original array to back the collection, so changes to the collection will be reflected in the array. Collections.toArray makes a (shallow) copy of the collection data. Making a copy is often what you would want anyway if you are returning an array. Asymmetrically, if you are passing as an argument you generally do not copy (unless storing as a field).

like image 153
Tom Hawtin - tackline Avatar answered Sep 28 '22 02:09

Tom Hawtin - tackline


Use Iterable. That's what it's for.

As you said, Iterable won't handle arrays.

You don't want to use multiple methods wrapping each other. That rules out Arrays.asList and Collection.toArray.

So the answer to your question is no, there isn't a way. But if you can use Lists, why would you ever use arrays?

I would still go with Iterable here. I like it better than Collection because in the past I've had classes that implemented Iterable but were not collections; this made it easy for them to lazily retrieve values as needed, and I could use the foreach loop on them.

like image 27
Michael Myers Avatar answered Sep 28 '22 01:09

Michael Myers