Can I write a for loop that iterates over both collections and arrays? The 2019 Stack Overflow...

Does the shape of a die affect the probability of a number being rolled?

Why was M87 targetted for the Event Horizon Telescope instead of Sagittarius A*?

Can we generate random numbers using irrational numbers like π and e?

If I score a critical hit on an 18 or higher, what are my chances of getting a critical hit if I roll 3d20?

Why do some words that are not inflected have an umlaut?

Can one be advised by a professor who is very far away?

The difference between dialogue marks

Reference request: Oldest number theory books with (unsolved) exercises?

How to answer pointed "are you quitting" questioning when I don't want them to suspect

How to manage monthly salary

Does coating your armor in silver add any effects?

Can a flute soloist sit?

Did Section 31 appear in Star Trek: The Next Generation?

Are there any other methods to apply to solving simultaneous equations?

Are spiders unable to hurt humans, especially very small spiders?

Is flight data recorder erased after every flight?

What does Linus Torvalds mean when he says that Git "never ever" tracks a file?

Can you compress metal and what would be the consequences?

Am I thawing this London Broil safely?

Origin of "cooter" meaning "vagina"

Time travel alters history but people keep saying nothing's changed

Is this app Icon Browser Safe/Legit?

Where to refill my bottle in India?

What is the accessibility of a package's `Private` context variables?



Can I write a for loop that iterates over both collections and arrays?



The 2019 Stack Overflow Developer Survey Results Are InHow to see if an object is an array without using reflection?Why doesn't Java Map extends Collection?How do I efficiently iterate over each entry in a Java Map?How can I concatenate two arrays in Java?Iterating through a Collection, avoiding ConcurrentModificationException when removing objects in a loopWhy is using “for…in” with array iteration a bad idea?A 'for' loop to iterate over an enum in JavaLoop through an array in JavaScriptEasy way to convert Iterable to CollectionHow can I add new array elements at the beginning of an array in Javascript?Loop through an array of strings in Bash?Ways to iterate over a list in Java





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







14















Is there a possibility to check if an object is either an array or a collection with one clause? What I am trying to achieve:



Assuming arrays implement Iterable, and assuming the Object foo could be either an array or a collection, I'd like to use a code snippet like this:



if (foo instanceof Iterable) {
for (Object f : (Iterable) foo) {
// do something with f
}
}


Unfortunately, an array cannot be cast to Iterable. Nor does it implement Collection. Are there any other possibilities to handle both in one loop like the above? Instead of -- of course -- using an if-else if-clause and two loops (which wouldn't be nice).



Edit: In response to these answers. I am aware of the isArray() method but in this case the casting in



...
for (Object f : (Iterable) foo) {
...


will fail. That'd a pity and a code redundancy since I would have to use two loops although a foreach-loop works both with Collections and Arrays.










share|improve this question

























  • The way I see it, foo must be declared as Object. So you have to cast anyway. Are you trying to cast just once?

    – ernest_k
    yesterday













  • The foreach-loop won't work if I cast it to Object -- you cannot iterate through objects.

    – Pawel Os.
    yesterday






  • 8





    It's a good idea to avoid a design that leads to this in the first place. Even if you had a common interface for this to work with just one for-each loop, you'd still have many type casts. Your code wouldn't be type-safe (Object[]? raw Iterable?)

    – ernest_k
    yesterday


















14















Is there a possibility to check if an object is either an array or a collection with one clause? What I am trying to achieve:



Assuming arrays implement Iterable, and assuming the Object foo could be either an array or a collection, I'd like to use a code snippet like this:



if (foo instanceof Iterable) {
for (Object f : (Iterable) foo) {
// do something with f
}
}


Unfortunately, an array cannot be cast to Iterable. Nor does it implement Collection. Are there any other possibilities to handle both in one loop like the above? Instead of -- of course -- using an if-else if-clause and two loops (which wouldn't be nice).



Edit: In response to these answers. I am aware of the isArray() method but in this case the casting in



...
for (Object f : (Iterable) foo) {
...


will fail. That'd a pity and a code redundancy since I would have to use two loops although a foreach-loop works both with Collections and Arrays.










share|improve this question

























  • The way I see it, foo must be declared as Object. So you have to cast anyway. Are you trying to cast just once?

    – ernest_k
    yesterday













  • The foreach-loop won't work if I cast it to Object -- you cannot iterate through objects.

    – Pawel Os.
    yesterday






  • 8





    It's a good idea to avoid a design that leads to this in the first place. Even if you had a common interface for this to work with just one for-each loop, you'd still have many type casts. Your code wouldn't be type-safe (Object[]? raw Iterable?)

    – ernest_k
    yesterday














14












14








14


3






Is there a possibility to check if an object is either an array or a collection with one clause? What I am trying to achieve:



Assuming arrays implement Iterable, and assuming the Object foo could be either an array or a collection, I'd like to use a code snippet like this:



if (foo instanceof Iterable) {
for (Object f : (Iterable) foo) {
// do something with f
}
}


Unfortunately, an array cannot be cast to Iterable. Nor does it implement Collection. Are there any other possibilities to handle both in one loop like the above? Instead of -- of course -- using an if-else if-clause and two loops (which wouldn't be nice).



Edit: In response to these answers. I am aware of the isArray() method but in this case the casting in



...
for (Object f : (Iterable) foo) {
...


will fail. That'd a pity and a code redundancy since I would have to use two loops although a foreach-loop works both with Collections and Arrays.










share|improve this question
















Is there a possibility to check if an object is either an array or a collection with one clause? What I am trying to achieve:



Assuming arrays implement Iterable, and assuming the Object foo could be either an array or a collection, I'd like to use a code snippet like this:



if (foo instanceof Iterable) {
for (Object f : (Iterable) foo) {
// do something with f
}
}


Unfortunately, an array cannot be cast to Iterable. Nor does it implement Collection. Are there any other possibilities to handle both in one loop like the above? Instead of -- of course -- using an if-else if-clause and two loops (which wouldn't be nice).



Edit: In response to these answers. I am aware of the isArray() method but in this case the casting in



...
for (Object f : (Iterable) foo) {
...


will fail. That'd a pity and a code redundancy since I would have to use two loops although a foreach-loop works both with Collections and Arrays.







java arrays collections






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited yesterday









John Kugelman

248k54406460




248k54406460










asked yesterday









Pawel Os.Pawel Os.

162116




162116













  • The way I see it, foo must be declared as Object. So you have to cast anyway. Are you trying to cast just once?

    – ernest_k
    yesterday













  • The foreach-loop won't work if I cast it to Object -- you cannot iterate through objects.

    – Pawel Os.
    yesterday






  • 8





    It's a good idea to avoid a design that leads to this in the first place. Even if you had a common interface for this to work with just one for-each loop, you'd still have many type casts. Your code wouldn't be type-safe (Object[]? raw Iterable?)

    – ernest_k
    yesterday



















  • The way I see it, foo must be declared as Object. So you have to cast anyway. Are you trying to cast just once?

    – ernest_k
    yesterday













  • The foreach-loop won't work if I cast it to Object -- you cannot iterate through objects.

    – Pawel Os.
    yesterday






  • 8





    It's a good idea to avoid a design that leads to this in the first place. Even if you had a common interface for this to work with just one for-each loop, you'd still have many type casts. Your code wouldn't be type-safe (Object[]? raw Iterable?)

    – ernest_k
    yesterday

















The way I see it, foo must be declared as Object. So you have to cast anyway. Are you trying to cast just once?

– ernest_k
yesterday







The way I see it, foo must be declared as Object. So you have to cast anyway. Are you trying to cast just once?

– ernest_k
yesterday















The foreach-loop won't work if I cast it to Object -- you cannot iterate through objects.

– Pawel Os.
yesterday





The foreach-loop won't work if I cast it to Object -- you cannot iterate through objects.

– Pawel Os.
yesterday




8




8





It's a good idea to avoid a design that leads to this in the first place. Even if you had a common interface for this to work with just one for-each loop, you'd still have many type casts. Your code wouldn't be type-safe (Object[]? raw Iterable?)

– ernest_k
yesterday





It's a good idea to avoid a design that leads to this in the first place. Even if you had a common interface for this to work with just one for-each loop, you'd still have many type casts. Your code wouldn't be type-safe (Object[]? raw Iterable?)

– ernest_k
yesterday












6 Answers
6






active

oldest

votes


















7














The other answers are all trying hard to answer the original title question:




Is there a common interface or superclass for arrays and collections?




But your real question is in the body:




Are there any other possibilities to handle both in one loop like the above?




The answer is: No, there's no way to write a single for loop that iterates over both collections and arrays.



You could jump through a bunch of hoops to turn the arrays into lists, but you'll almost certainly end up with a bigger mess than if you just wrote two (or more) loops. Calling getClass().isArray() tells you what you have but you still can't work with it without some sort of cast. Arrays.asList() doesn't work for arrays of primitives.






share|improve this answer


























  • Thank you for this response. It's a pity that you cannot abstract from Arrays/Collection and primitive/objects in Java, as the loop construction would remain the same and would make the code more readable. But I guess that's just the way it is and we have to live with it.

    – Pawel Os.
    20 hours ago



















16














Regarding a condition to check if foo is either a collection or an array:



Class#isAssignableFrom may come in handy.



Class<?> fooClass = foo.getClass();
boolean isArrayOrCollection = Collection.class.isAssignableFrom(fooClass) ||
Object[].class.isAssignableFrom(fooClass);


I reasonably assume you won't test it on primitive arrays since you have collections which work only with the wrapper classes.



I guess you can safely replace Object[].class.isAssignableFrom(fooClass) with fooClass.isArray()



boolean isArrayOrCollection = Collection.class.isAssignableFrom(fooClass) ||
fooClass.isArray();


and it would also work for a primitive array class.





I've run a small "test"



class Test {
public static void main(String[] args) {
Predicate<Class<?>> p = c -> Collection.class.isAssignableFrom(c) ||
c.isArray();

System.out.println(p.test(new int[0].getClass()));
System.out.println(p.test(new Integer[0].getClass()));
System.out.println(p.test(Collections.emptyList().getClass()));
System.out.println(p.test(Collections.emptySet().getClass()));

System.out.println(p.test(Collections.emptyMap().getClass()));
}
}


which results in



true
true
true
true
false




Regarding a generic loop that would run over both arrays and
collections:



You simply can't write an accurate construction to handle this: Collection (or Iterable) and Object[] have little in common (Object as a common parent and its methods are not enough).



I think it's sensible to build own abstraction which would treat collections and arrays in the same manner. Having no particular context, I can come up with a simple idea of two subclasses, each of which defining how its source (either a collection or an array) should be iterated. Then, programming to an interface will help to manage them equally.



A very simplified example would be:



interface Abstraction<T> {
void iterate(Consumer<? super T> action);

static <T> Abstraction<T> of(Collection<T> collection) {
return new CollectionAbstraction<>(collection);
}
static <T> Abstraction<T> of(T[] array) {
return new ArrayAbstraction<>(array);
}
static IntArrayAbstraction of(int[] array) {
return new IntArrayAbstraction(array);
}
}

class CollectionAbstraction<T> implements Abstraction<T> {
Collection<T> source;

public CollectionAbstraction(Collection<T> source) {
this.source = source;
}

@Override
public void iterate(Consumer<? super T> action) {
source.forEach(action);
}
}

class ArrayAbstraction<T> implements Abstraction<T> {
T[] source;

public ArrayAbstraction(T[] source) {
this.source = source;
}

@Override
public void iterate(Consumer<? super T> action) {
for (T t : source) {
action.accept(t);
}
}
}

class IntArrayAbstraction implements Abstraction<Integer> {
int[] source;

public IntArrayAbstraction(int[] source) {
this.source = source;
}

@Override
public void iterate(Consumer<? super Integer> action) {
for (int t : source) {
action.accept(t);
}
}
}

class Test {
public static void main(String[] args) {
Abstraction.of(new Integer[] {1, 2, 3}).iterate(System.out::println);
Abstraction.of(Arrays.asList(1, 2, 3)).iterate(System.out::println);
Abstraction.of(new int[] {1, 2, 3}).iterate(System.out::println);
}
}


I believe the approach above is pretty versatile. You don't depend on how a certain source is iterated, you may selectively modify them.






share|improve this answer


























  • Whereas this seems good practical advice for the OP, it does not directly respond to the actual question, which inquires about a common supertype of collections and arrays.

    – John Bollinger
    yesterday






  • 3





    @JohnBollinger I thought it was obvious from the comments that there is no neat solution, so I dropped that part. Now I elaborated on this in the last paragraphs.

    – Andrew Tobilko
    yesterday






  • 1





    The abstraction described in the second half of this answer is unnecessary, because something equivalent already exists in the standard library. Just replace Abstraction with Collection, and Abstraction.of(T[]) with Arrays.asList.

    – David
    yesterday











  • @David what would you replace Abstraction with for arrays of primitives?

    – Andrew Tobilko
    23 hours ago













  • Abstraction doesn't work on arrays of primitives because T has to be a subclass of Object. Change new Integer[] to new int[] and it fails to compile.

    – John Kugelman
    16 hours ago



















6














Depending on what you are trying to do, you might want to implement two similar methods:



public <T> void iterateOver(List<T> list) {
// do whatever you want to do with your list
}

public <T> void iterateOver(T[] array) {
this.iterateOver(Arrays.asList(array));
}


Or maybe even have an interface for this:



interface ExtendedIterableConsumer<T> {

public void iterateOver(List<T> list);

public default void iterateOver(T[] array) {
this.iterateOver(Arrays.asList(array));

}


I am not sure if that helps you, because you seem to already have the object in question in a variable somewhere. But if you can address that problem one level higher, it might be useful.






share|improve this answer

































    4














    You could write a helper method for this:



    @SuppressWarnings("unchecked")
    public static <E> void forEach(Object arrayOrIterable, Consumer<? super E> action) {
    Objects.requireNonNull(arrayOrIterable);
    if (arrayOrIterable instanceof Iterable) {
    for (Object o : (Iterable<?>) arrayOrIterable) {
    action.accept((E) o);
    }
    } else if (arrayOrIterable.getClass().isArray()) {
    int length = Array.getLength(arrayOrIterable);
    for (int i = 0; i < length; i++) {
    action.accept((E) Array.get(arrayOrIterable, i));
    }
    } else {
    throw new IllegalArgumentException("not an array nor iterable: " + arrayOrIterable.getClass());
    }
    }


    The second branch makes use of the java.reflect.Array class which provides helper methods (may be slow), to get the length of an array and the element at a given index.



    You may call it like this:



    int[] ints = {1, 2, 3, 4};
    forEach(ints, (Integer i) -> System.out.println(i));

    List<Integer> ints = Arrays.asList(1, 2, 3, 4);
    forEach(ints, (Integer i) -> System.out.println(i));


    Due to the nature of generics, this method may throw a ClassCastException, e.g. this call:



    int[] ints = {1, 2, 3, 4};
    forEach(ints, (String s) -> System.out.println(s));


    Would result in:



    java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String





    share|improve this answer


























    • I wouldn't dare to name the parameter arrayOrIterable since it's an Object and it might be anything

      – Andrew Tobilko
      yesterday






    • 1





      @AndrewTobilko Well this method only works with an array or an iterable, and will throw an exception for every other Object, so this should help as documentation that really one of those two types is expected

      – Lino
      yesterday











    • oh, I get you. It's a matter of personal preference/style, I guess.

      – Andrew Tobilko
      yesterday






    • 2





      @AndrewTobilko It really is something that is purely opinion based, best would be of course an extensive java-doc stating what can be passed into this method, what exceptions may be thrown etc.

      – Lino
      yesterday



















    4














    You can check if object is array by using isArray() method from Class



    if (foo != null && (foo.getClass().isArray() || foo instanceof Collection<?>)){

    }


    Edit:



    In terms of iterating over this foo object, there is no simple solution. However you could try something like this:



    private void iterate(@NotNull Object foo) {
    if (foo instanceof Collection<?>) {
    for (Object o : ((Collection<?>) foo)) {
    chandleYourObject(o);
    }
    }

    if (foo.getClass().isArray()) {
    if (foo.getClass().isPrimitive()) {
    checkPrimitiveTypes(foo);
    }
    if (foo instanceof Object[]) {
    for (Object o : (Object[]) foo) {
    chandleYourObject(o);
    }
    }
    }
    }

    private void checkPrimitiveTypes(Object foo) {
    if (foo instanceof int[]) {
    for (int i : (int[]) foo) {

    }
    }
    //And the rest of primitive types
    }

    private void chandleYourObject(Object o ){
    //What you want to do with your object
    }





    share|improve this answer


























    • you can just check if foo instanceof Collection<?>. Shorter and more clear in my opinion. No nee to use Collection.class.isAssignableFrom. I've added partial answer because at first you didn't include isArray() method in your answer :)

      – Mershel
      yesterday













    • Though, I still believe that Collection.class.isAssignableFrom(fooClass) is more flexible than foo instanceof Collection because Collection.class could be any class at runtime (a dynamically obtained one, I mean)

      – Andrew Tobilko
      yesterday













    • Wouldn't that throw NPE when we would pass int[] i = null? I think that there will be no difference between Collection.class.isAssignableFrom(fooClass) and foo instanceof Collection<?>, that is just up to what you prefer and what is more readable for you ;)

      – Mershel
      yesterday



















    4














    Arrays are Objects:



    https://docs.oracle.com/javase/specs/jls/se8/html/jls-10.html



    AbstractCollections also extend Object:



    https://docs.oracle.com/javase/8/docs/api/java/util/AbstractCollection.html



    So yes there is a common superclass, but unfortunately this isn't really going to help you.



    I would suggest your best bet is to use:



    List<> someList = Arrays.asList(sourceArray)


    This will convert your array into a collection that implements Iterable. You will of course need to work out if the initial object is an Array or a Collection in advance and only call the above if it is an array, here are some options for doing that:



    boolean isArray = myArray.getClass().isArray();
    boolean isCollection = Collection.class.isAssignableFrom(myList.getClass());





    share|improve this answer





















    • 4





      Arrays.asList() will sadly not work with primitive arrays

      – Lino
      yesterday






    • 1





      Agreed, but I'm making the assumption here that the OP is not using primitive arrays. If they are they could do something like Integer[] boxedInts = IntStream.of(ints).boxed().toArray(Integer[]::new); (Assuming they aren't using a byte[] array, in which case it gets more complex)

      – Ardesco
      yesterday






    • 1





      Arrays is a utility class that "contains various methods for manipulating arrays". It is not the superclass of arrays.

      – Solomon Ucko
      yesterday






    • 1





      True, updated the answer to point towards Java documentation that states Arrays are Objects instead,

      – Ardesco
      yesterday












    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55588278%2fcan-i-write-a-for-loop-that-iterates-over-both-collections-and-arrays%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    6 Answers
    6






    active

    oldest

    votes








    6 Answers
    6






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    7














    The other answers are all trying hard to answer the original title question:




    Is there a common interface or superclass for arrays and collections?




    But your real question is in the body:




    Are there any other possibilities to handle both in one loop like the above?




    The answer is: No, there's no way to write a single for loop that iterates over both collections and arrays.



    You could jump through a bunch of hoops to turn the arrays into lists, but you'll almost certainly end up with a bigger mess than if you just wrote two (or more) loops. Calling getClass().isArray() tells you what you have but you still can't work with it without some sort of cast. Arrays.asList() doesn't work for arrays of primitives.






    share|improve this answer


























    • Thank you for this response. It's a pity that you cannot abstract from Arrays/Collection and primitive/objects in Java, as the loop construction would remain the same and would make the code more readable. But I guess that's just the way it is and we have to live with it.

      – Pawel Os.
      20 hours ago
















    7














    The other answers are all trying hard to answer the original title question:




    Is there a common interface or superclass for arrays and collections?




    But your real question is in the body:




    Are there any other possibilities to handle both in one loop like the above?




    The answer is: No, there's no way to write a single for loop that iterates over both collections and arrays.



    You could jump through a bunch of hoops to turn the arrays into lists, but you'll almost certainly end up with a bigger mess than if you just wrote two (or more) loops. Calling getClass().isArray() tells you what you have but you still can't work with it without some sort of cast. Arrays.asList() doesn't work for arrays of primitives.






    share|improve this answer


























    • Thank you for this response. It's a pity that you cannot abstract from Arrays/Collection and primitive/objects in Java, as the loop construction would remain the same and would make the code more readable. But I guess that's just the way it is and we have to live with it.

      – Pawel Os.
      20 hours ago














    7












    7








    7







    The other answers are all trying hard to answer the original title question:




    Is there a common interface or superclass for arrays and collections?




    But your real question is in the body:




    Are there any other possibilities to handle both in one loop like the above?




    The answer is: No, there's no way to write a single for loop that iterates over both collections and arrays.



    You could jump through a bunch of hoops to turn the arrays into lists, but you'll almost certainly end up with a bigger mess than if you just wrote two (or more) loops. Calling getClass().isArray() tells you what you have but you still can't work with it without some sort of cast. Arrays.asList() doesn't work for arrays of primitives.






    share|improve this answer















    The other answers are all trying hard to answer the original title question:




    Is there a common interface or superclass for arrays and collections?




    But your real question is in the body:




    Are there any other possibilities to handle both in one loop like the above?




    The answer is: No, there's no way to write a single for loop that iterates over both collections and arrays.



    You could jump through a bunch of hoops to turn the arrays into lists, but you'll almost certainly end up with a bigger mess than if you just wrote two (or more) loops. Calling getClass().isArray() tells you what you have but you still can't work with it without some sort of cast. Arrays.asList() doesn't work for arrays of primitives.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited yesterday

























    answered yesterday









    John KugelmanJohn Kugelman

    248k54406460




    248k54406460













    • Thank you for this response. It's a pity that you cannot abstract from Arrays/Collection and primitive/objects in Java, as the loop construction would remain the same and would make the code more readable. But I guess that's just the way it is and we have to live with it.

      – Pawel Os.
      20 hours ago



















    • Thank you for this response. It's a pity that you cannot abstract from Arrays/Collection and primitive/objects in Java, as the loop construction would remain the same and would make the code more readable. But I guess that's just the way it is and we have to live with it.

      – Pawel Os.
      20 hours ago

















    Thank you for this response. It's a pity that you cannot abstract from Arrays/Collection and primitive/objects in Java, as the loop construction would remain the same and would make the code more readable. But I guess that's just the way it is and we have to live with it.

    – Pawel Os.
    20 hours ago





    Thank you for this response. It's a pity that you cannot abstract from Arrays/Collection and primitive/objects in Java, as the loop construction would remain the same and would make the code more readable. But I guess that's just the way it is and we have to live with it.

    – Pawel Os.
    20 hours ago













    16














    Regarding a condition to check if foo is either a collection or an array:



    Class#isAssignableFrom may come in handy.



    Class<?> fooClass = foo.getClass();
    boolean isArrayOrCollection = Collection.class.isAssignableFrom(fooClass) ||
    Object[].class.isAssignableFrom(fooClass);


    I reasonably assume you won't test it on primitive arrays since you have collections which work only with the wrapper classes.



    I guess you can safely replace Object[].class.isAssignableFrom(fooClass) with fooClass.isArray()



    boolean isArrayOrCollection = Collection.class.isAssignableFrom(fooClass) ||
    fooClass.isArray();


    and it would also work for a primitive array class.





    I've run a small "test"



    class Test {
    public static void main(String[] args) {
    Predicate<Class<?>> p = c -> Collection.class.isAssignableFrom(c) ||
    c.isArray();

    System.out.println(p.test(new int[0].getClass()));
    System.out.println(p.test(new Integer[0].getClass()));
    System.out.println(p.test(Collections.emptyList().getClass()));
    System.out.println(p.test(Collections.emptySet().getClass()));

    System.out.println(p.test(Collections.emptyMap().getClass()));
    }
    }


    which results in



    true
    true
    true
    true
    false




    Regarding a generic loop that would run over both arrays and
    collections:



    You simply can't write an accurate construction to handle this: Collection (or Iterable) and Object[] have little in common (Object as a common parent and its methods are not enough).



    I think it's sensible to build own abstraction which would treat collections and arrays in the same manner. Having no particular context, I can come up with a simple idea of two subclasses, each of which defining how its source (either a collection or an array) should be iterated. Then, programming to an interface will help to manage them equally.



    A very simplified example would be:



    interface Abstraction<T> {
    void iterate(Consumer<? super T> action);

    static <T> Abstraction<T> of(Collection<T> collection) {
    return new CollectionAbstraction<>(collection);
    }
    static <T> Abstraction<T> of(T[] array) {
    return new ArrayAbstraction<>(array);
    }
    static IntArrayAbstraction of(int[] array) {
    return new IntArrayAbstraction(array);
    }
    }

    class CollectionAbstraction<T> implements Abstraction<T> {
    Collection<T> source;

    public CollectionAbstraction(Collection<T> source) {
    this.source = source;
    }

    @Override
    public void iterate(Consumer<? super T> action) {
    source.forEach(action);
    }
    }

    class ArrayAbstraction<T> implements Abstraction<T> {
    T[] source;

    public ArrayAbstraction(T[] source) {
    this.source = source;
    }

    @Override
    public void iterate(Consumer<? super T> action) {
    for (T t : source) {
    action.accept(t);
    }
    }
    }

    class IntArrayAbstraction implements Abstraction<Integer> {
    int[] source;

    public IntArrayAbstraction(int[] source) {
    this.source = source;
    }

    @Override
    public void iterate(Consumer<? super Integer> action) {
    for (int t : source) {
    action.accept(t);
    }
    }
    }

    class Test {
    public static void main(String[] args) {
    Abstraction.of(new Integer[] {1, 2, 3}).iterate(System.out::println);
    Abstraction.of(Arrays.asList(1, 2, 3)).iterate(System.out::println);
    Abstraction.of(new int[] {1, 2, 3}).iterate(System.out::println);
    }
    }


    I believe the approach above is pretty versatile. You don't depend on how a certain source is iterated, you may selectively modify them.






    share|improve this answer


























    • Whereas this seems good practical advice for the OP, it does not directly respond to the actual question, which inquires about a common supertype of collections and arrays.

      – John Bollinger
      yesterday






    • 3





      @JohnBollinger I thought it was obvious from the comments that there is no neat solution, so I dropped that part. Now I elaborated on this in the last paragraphs.

      – Andrew Tobilko
      yesterday






    • 1





      The abstraction described in the second half of this answer is unnecessary, because something equivalent already exists in the standard library. Just replace Abstraction with Collection, and Abstraction.of(T[]) with Arrays.asList.

      – David
      yesterday











    • @David what would you replace Abstraction with for arrays of primitives?

      – Andrew Tobilko
      23 hours ago













    • Abstraction doesn't work on arrays of primitives because T has to be a subclass of Object. Change new Integer[] to new int[] and it fails to compile.

      – John Kugelman
      16 hours ago
















    16














    Regarding a condition to check if foo is either a collection or an array:



    Class#isAssignableFrom may come in handy.



    Class<?> fooClass = foo.getClass();
    boolean isArrayOrCollection = Collection.class.isAssignableFrom(fooClass) ||
    Object[].class.isAssignableFrom(fooClass);


    I reasonably assume you won't test it on primitive arrays since you have collections which work only with the wrapper classes.



    I guess you can safely replace Object[].class.isAssignableFrom(fooClass) with fooClass.isArray()



    boolean isArrayOrCollection = Collection.class.isAssignableFrom(fooClass) ||
    fooClass.isArray();


    and it would also work for a primitive array class.





    I've run a small "test"



    class Test {
    public static void main(String[] args) {
    Predicate<Class<?>> p = c -> Collection.class.isAssignableFrom(c) ||
    c.isArray();

    System.out.println(p.test(new int[0].getClass()));
    System.out.println(p.test(new Integer[0].getClass()));
    System.out.println(p.test(Collections.emptyList().getClass()));
    System.out.println(p.test(Collections.emptySet().getClass()));

    System.out.println(p.test(Collections.emptyMap().getClass()));
    }
    }


    which results in



    true
    true
    true
    true
    false




    Regarding a generic loop that would run over both arrays and
    collections:



    You simply can't write an accurate construction to handle this: Collection (or Iterable) and Object[] have little in common (Object as a common parent and its methods are not enough).



    I think it's sensible to build own abstraction which would treat collections and arrays in the same manner. Having no particular context, I can come up with a simple idea of two subclasses, each of which defining how its source (either a collection or an array) should be iterated. Then, programming to an interface will help to manage them equally.



    A very simplified example would be:



    interface Abstraction<T> {
    void iterate(Consumer<? super T> action);

    static <T> Abstraction<T> of(Collection<T> collection) {
    return new CollectionAbstraction<>(collection);
    }
    static <T> Abstraction<T> of(T[] array) {
    return new ArrayAbstraction<>(array);
    }
    static IntArrayAbstraction of(int[] array) {
    return new IntArrayAbstraction(array);
    }
    }

    class CollectionAbstraction<T> implements Abstraction<T> {
    Collection<T> source;

    public CollectionAbstraction(Collection<T> source) {
    this.source = source;
    }

    @Override
    public void iterate(Consumer<? super T> action) {
    source.forEach(action);
    }
    }

    class ArrayAbstraction<T> implements Abstraction<T> {
    T[] source;

    public ArrayAbstraction(T[] source) {
    this.source = source;
    }

    @Override
    public void iterate(Consumer<? super T> action) {
    for (T t : source) {
    action.accept(t);
    }
    }
    }

    class IntArrayAbstraction implements Abstraction<Integer> {
    int[] source;

    public IntArrayAbstraction(int[] source) {
    this.source = source;
    }

    @Override
    public void iterate(Consumer<? super Integer> action) {
    for (int t : source) {
    action.accept(t);
    }
    }
    }

    class Test {
    public static void main(String[] args) {
    Abstraction.of(new Integer[] {1, 2, 3}).iterate(System.out::println);
    Abstraction.of(Arrays.asList(1, 2, 3)).iterate(System.out::println);
    Abstraction.of(new int[] {1, 2, 3}).iterate(System.out::println);
    }
    }


    I believe the approach above is pretty versatile. You don't depend on how a certain source is iterated, you may selectively modify them.






    share|improve this answer


























    • Whereas this seems good practical advice for the OP, it does not directly respond to the actual question, which inquires about a common supertype of collections and arrays.

      – John Bollinger
      yesterday






    • 3





      @JohnBollinger I thought it was obvious from the comments that there is no neat solution, so I dropped that part. Now I elaborated on this in the last paragraphs.

      – Andrew Tobilko
      yesterday






    • 1





      The abstraction described in the second half of this answer is unnecessary, because something equivalent already exists in the standard library. Just replace Abstraction with Collection, and Abstraction.of(T[]) with Arrays.asList.

      – David
      yesterday











    • @David what would you replace Abstraction with for arrays of primitives?

      – Andrew Tobilko
      23 hours ago













    • Abstraction doesn't work on arrays of primitives because T has to be a subclass of Object. Change new Integer[] to new int[] and it fails to compile.

      – John Kugelman
      16 hours ago














    16












    16








    16







    Regarding a condition to check if foo is either a collection or an array:



    Class#isAssignableFrom may come in handy.



    Class<?> fooClass = foo.getClass();
    boolean isArrayOrCollection = Collection.class.isAssignableFrom(fooClass) ||
    Object[].class.isAssignableFrom(fooClass);


    I reasonably assume you won't test it on primitive arrays since you have collections which work only with the wrapper classes.



    I guess you can safely replace Object[].class.isAssignableFrom(fooClass) with fooClass.isArray()



    boolean isArrayOrCollection = Collection.class.isAssignableFrom(fooClass) ||
    fooClass.isArray();


    and it would also work for a primitive array class.





    I've run a small "test"



    class Test {
    public static void main(String[] args) {
    Predicate<Class<?>> p = c -> Collection.class.isAssignableFrom(c) ||
    c.isArray();

    System.out.println(p.test(new int[0].getClass()));
    System.out.println(p.test(new Integer[0].getClass()));
    System.out.println(p.test(Collections.emptyList().getClass()));
    System.out.println(p.test(Collections.emptySet().getClass()));

    System.out.println(p.test(Collections.emptyMap().getClass()));
    }
    }


    which results in



    true
    true
    true
    true
    false




    Regarding a generic loop that would run over both arrays and
    collections:



    You simply can't write an accurate construction to handle this: Collection (or Iterable) and Object[] have little in common (Object as a common parent and its methods are not enough).



    I think it's sensible to build own abstraction which would treat collections and arrays in the same manner. Having no particular context, I can come up with a simple idea of two subclasses, each of which defining how its source (either a collection or an array) should be iterated. Then, programming to an interface will help to manage them equally.



    A very simplified example would be:



    interface Abstraction<T> {
    void iterate(Consumer<? super T> action);

    static <T> Abstraction<T> of(Collection<T> collection) {
    return new CollectionAbstraction<>(collection);
    }
    static <T> Abstraction<T> of(T[] array) {
    return new ArrayAbstraction<>(array);
    }
    static IntArrayAbstraction of(int[] array) {
    return new IntArrayAbstraction(array);
    }
    }

    class CollectionAbstraction<T> implements Abstraction<T> {
    Collection<T> source;

    public CollectionAbstraction(Collection<T> source) {
    this.source = source;
    }

    @Override
    public void iterate(Consumer<? super T> action) {
    source.forEach(action);
    }
    }

    class ArrayAbstraction<T> implements Abstraction<T> {
    T[] source;

    public ArrayAbstraction(T[] source) {
    this.source = source;
    }

    @Override
    public void iterate(Consumer<? super T> action) {
    for (T t : source) {
    action.accept(t);
    }
    }
    }

    class IntArrayAbstraction implements Abstraction<Integer> {
    int[] source;

    public IntArrayAbstraction(int[] source) {
    this.source = source;
    }

    @Override
    public void iterate(Consumer<? super Integer> action) {
    for (int t : source) {
    action.accept(t);
    }
    }
    }

    class Test {
    public static void main(String[] args) {
    Abstraction.of(new Integer[] {1, 2, 3}).iterate(System.out::println);
    Abstraction.of(Arrays.asList(1, 2, 3)).iterate(System.out::println);
    Abstraction.of(new int[] {1, 2, 3}).iterate(System.out::println);
    }
    }


    I believe the approach above is pretty versatile. You don't depend on how a certain source is iterated, you may selectively modify them.






    share|improve this answer















    Regarding a condition to check if foo is either a collection or an array:



    Class#isAssignableFrom may come in handy.



    Class<?> fooClass = foo.getClass();
    boolean isArrayOrCollection = Collection.class.isAssignableFrom(fooClass) ||
    Object[].class.isAssignableFrom(fooClass);


    I reasonably assume you won't test it on primitive arrays since you have collections which work only with the wrapper classes.



    I guess you can safely replace Object[].class.isAssignableFrom(fooClass) with fooClass.isArray()



    boolean isArrayOrCollection = Collection.class.isAssignableFrom(fooClass) ||
    fooClass.isArray();


    and it would also work for a primitive array class.





    I've run a small "test"



    class Test {
    public static void main(String[] args) {
    Predicate<Class<?>> p = c -> Collection.class.isAssignableFrom(c) ||
    c.isArray();

    System.out.println(p.test(new int[0].getClass()));
    System.out.println(p.test(new Integer[0].getClass()));
    System.out.println(p.test(Collections.emptyList().getClass()));
    System.out.println(p.test(Collections.emptySet().getClass()));

    System.out.println(p.test(Collections.emptyMap().getClass()));
    }
    }


    which results in



    true
    true
    true
    true
    false




    Regarding a generic loop that would run over both arrays and
    collections:



    You simply can't write an accurate construction to handle this: Collection (or Iterable) and Object[] have little in common (Object as a common parent and its methods are not enough).



    I think it's sensible to build own abstraction which would treat collections and arrays in the same manner. Having no particular context, I can come up with a simple idea of two subclasses, each of which defining how its source (either a collection or an array) should be iterated. Then, programming to an interface will help to manage them equally.



    A very simplified example would be:



    interface Abstraction<T> {
    void iterate(Consumer<? super T> action);

    static <T> Abstraction<T> of(Collection<T> collection) {
    return new CollectionAbstraction<>(collection);
    }
    static <T> Abstraction<T> of(T[] array) {
    return new ArrayAbstraction<>(array);
    }
    static IntArrayAbstraction of(int[] array) {
    return new IntArrayAbstraction(array);
    }
    }

    class CollectionAbstraction<T> implements Abstraction<T> {
    Collection<T> source;

    public CollectionAbstraction(Collection<T> source) {
    this.source = source;
    }

    @Override
    public void iterate(Consumer<? super T> action) {
    source.forEach(action);
    }
    }

    class ArrayAbstraction<T> implements Abstraction<T> {
    T[] source;

    public ArrayAbstraction(T[] source) {
    this.source = source;
    }

    @Override
    public void iterate(Consumer<? super T> action) {
    for (T t : source) {
    action.accept(t);
    }
    }
    }

    class IntArrayAbstraction implements Abstraction<Integer> {
    int[] source;

    public IntArrayAbstraction(int[] source) {
    this.source = source;
    }

    @Override
    public void iterate(Consumer<? super Integer> action) {
    for (int t : source) {
    action.accept(t);
    }
    }
    }

    class Test {
    public static void main(String[] args) {
    Abstraction.of(new Integer[] {1, 2, 3}).iterate(System.out::println);
    Abstraction.of(Arrays.asList(1, 2, 3)).iterate(System.out::println);
    Abstraction.of(new int[] {1, 2, 3}).iterate(System.out::println);
    }
    }


    I believe the approach above is pretty versatile. You don't depend on how a certain source is iterated, you may selectively modify them.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 15 hours ago

























    answered yesterday









    Andrew TobilkoAndrew Tobilko

    28.6k104591




    28.6k104591













    • Whereas this seems good practical advice for the OP, it does not directly respond to the actual question, which inquires about a common supertype of collections and arrays.

      – John Bollinger
      yesterday






    • 3





      @JohnBollinger I thought it was obvious from the comments that there is no neat solution, so I dropped that part. Now I elaborated on this in the last paragraphs.

      – Andrew Tobilko
      yesterday






    • 1





      The abstraction described in the second half of this answer is unnecessary, because something equivalent already exists in the standard library. Just replace Abstraction with Collection, and Abstraction.of(T[]) with Arrays.asList.

      – David
      yesterday











    • @David what would you replace Abstraction with for arrays of primitives?

      – Andrew Tobilko
      23 hours ago













    • Abstraction doesn't work on arrays of primitives because T has to be a subclass of Object. Change new Integer[] to new int[] and it fails to compile.

      – John Kugelman
      16 hours ago



















    • Whereas this seems good practical advice for the OP, it does not directly respond to the actual question, which inquires about a common supertype of collections and arrays.

      – John Bollinger
      yesterday






    • 3





      @JohnBollinger I thought it was obvious from the comments that there is no neat solution, so I dropped that part. Now I elaborated on this in the last paragraphs.

      – Andrew Tobilko
      yesterday






    • 1





      The abstraction described in the second half of this answer is unnecessary, because something equivalent already exists in the standard library. Just replace Abstraction with Collection, and Abstraction.of(T[]) with Arrays.asList.

      – David
      yesterday











    • @David what would you replace Abstraction with for arrays of primitives?

      – Andrew Tobilko
      23 hours ago













    • Abstraction doesn't work on arrays of primitives because T has to be a subclass of Object. Change new Integer[] to new int[] and it fails to compile.

      – John Kugelman
      16 hours ago

















    Whereas this seems good practical advice for the OP, it does not directly respond to the actual question, which inquires about a common supertype of collections and arrays.

    – John Bollinger
    yesterday





    Whereas this seems good practical advice for the OP, it does not directly respond to the actual question, which inquires about a common supertype of collections and arrays.

    – John Bollinger
    yesterday




    3




    3





    @JohnBollinger I thought it was obvious from the comments that there is no neat solution, so I dropped that part. Now I elaborated on this in the last paragraphs.

    – Andrew Tobilko
    yesterday





    @JohnBollinger I thought it was obvious from the comments that there is no neat solution, so I dropped that part. Now I elaborated on this in the last paragraphs.

    – Andrew Tobilko
    yesterday




    1




    1





    The abstraction described in the second half of this answer is unnecessary, because something equivalent already exists in the standard library. Just replace Abstraction with Collection, and Abstraction.of(T[]) with Arrays.asList.

    – David
    yesterday





    The abstraction described in the second half of this answer is unnecessary, because something equivalent already exists in the standard library. Just replace Abstraction with Collection, and Abstraction.of(T[]) with Arrays.asList.

    – David
    yesterday













    @David what would you replace Abstraction with for arrays of primitives?

    – Andrew Tobilko
    23 hours ago







    @David what would you replace Abstraction with for arrays of primitives?

    – Andrew Tobilko
    23 hours ago















    Abstraction doesn't work on arrays of primitives because T has to be a subclass of Object. Change new Integer[] to new int[] and it fails to compile.

    – John Kugelman
    16 hours ago





    Abstraction doesn't work on arrays of primitives because T has to be a subclass of Object. Change new Integer[] to new int[] and it fails to compile.

    – John Kugelman
    16 hours ago











    6














    Depending on what you are trying to do, you might want to implement two similar methods:



    public <T> void iterateOver(List<T> list) {
    // do whatever you want to do with your list
    }

    public <T> void iterateOver(T[] array) {
    this.iterateOver(Arrays.asList(array));
    }


    Or maybe even have an interface for this:



    interface ExtendedIterableConsumer<T> {

    public void iterateOver(List<T> list);

    public default void iterateOver(T[] array) {
    this.iterateOver(Arrays.asList(array));

    }


    I am not sure if that helps you, because you seem to already have the object in question in a variable somewhere. But if you can address that problem one level higher, it might be useful.






    share|improve this answer






























      6














      Depending on what you are trying to do, you might want to implement two similar methods:



      public <T> void iterateOver(List<T> list) {
      // do whatever you want to do with your list
      }

      public <T> void iterateOver(T[] array) {
      this.iterateOver(Arrays.asList(array));
      }


      Or maybe even have an interface for this:



      interface ExtendedIterableConsumer<T> {

      public void iterateOver(List<T> list);

      public default void iterateOver(T[] array) {
      this.iterateOver(Arrays.asList(array));

      }


      I am not sure if that helps you, because you seem to already have the object in question in a variable somewhere. But if you can address that problem one level higher, it might be useful.






      share|improve this answer




























        6












        6








        6







        Depending on what you are trying to do, you might want to implement two similar methods:



        public <T> void iterateOver(List<T> list) {
        // do whatever you want to do with your list
        }

        public <T> void iterateOver(T[] array) {
        this.iterateOver(Arrays.asList(array));
        }


        Or maybe even have an interface for this:



        interface ExtendedIterableConsumer<T> {

        public void iterateOver(List<T> list);

        public default void iterateOver(T[] array) {
        this.iterateOver(Arrays.asList(array));

        }


        I am not sure if that helps you, because you seem to already have the object in question in a variable somewhere. But if you can address that problem one level higher, it might be useful.






        share|improve this answer















        Depending on what you are trying to do, you might want to implement two similar methods:



        public <T> void iterateOver(List<T> list) {
        // do whatever you want to do with your list
        }

        public <T> void iterateOver(T[] array) {
        this.iterateOver(Arrays.asList(array));
        }


        Or maybe even have an interface for this:



        interface ExtendedIterableConsumer<T> {

        public void iterateOver(List<T> list);

        public default void iterateOver(T[] array) {
        this.iterateOver(Arrays.asList(array));

        }


        I am not sure if that helps you, because you seem to already have the object in question in a variable somewhere. But if you can address that problem one level higher, it might be useful.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited yesterday

























        answered yesterday









        glglglglglgl

        68.2k796169




        68.2k796169























            4














            You could write a helper method for this:



            @SuppressWarnings("unchecked")
            public static <E> void forEach(Object arrayOrIterable, Consumer<? super E> action) {
            Objects.requireNonNull(arrayOrIterable);
            if (arrayOrIterable instanceof Iterable) {
            for (Object o : (Iterable<?>) arrayOrIterable) {
            action.accept((E) o);
            }
            } else if (arrayOrIterable.getClass().isArray()) {
            int length = Array.getLength(arrayOrIterable);
            for (int i = 0; i < length; i++) {
            action.accept((E) Array.get(arrayOrIterable, i));
            }
            } else {
            throw new IllegalArgumentException("not an array nor iterable: " + arrayOrIterable.getClass());
            }
            }


            The second branch makes use of the java.reflect.Array class which provides helper methods (may be slow), to get the length of an array and the element at a given index.



            You may call it like this:



            int[] ints = {1, 2, 3, 4};
            forEach(ints, (Integer i) -> System.out.println(i));

            List<Integer> ints = Arrays.asList(1, 2, 3, 4);
            forEach(ints, (Integer i) -> System.out.println(i));


            Due to the nature of generics, this method may throw a ClassCastException, e.g. this call:



            int[] ints = {1, 2, 3, 4};
            forEach(ints, (String s) -> System.out.println(s));


            Would result in:



            java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String





            share|improve this answer


























            • I wouldn't dare to name the parameter arrayOrIterable since it's an Object and it might be anything

              – Andrew Tobilko
              yesterday






            • 1





              @AndrewTobilko Well this method only works with an array or an iterable, and will throw an exception for every other Object, so this should help as documentation that really one of those two types is expected

              – Lino
              yesterday











            • oh, I get you. It's a matter of personal preference/style, I guess.

              – Andrew Tobilko
              yesterday






            • 2





              @AndrewTobilko It really is something that is purely opinion based, best would be of course an extensive java-doc stating what can be passed into this method, what exceptions may be thrown etc.

              – Lino
              yesterday
















            4














            You could write a helper method for this:



            @SuppressWarnings("unchecked")
            public static <E> void forEach(Object arrayOrIterable, Consumer<? super E> action) {
            Objects.requireNonNull(arrayOrIterable);
            if (arrayOrIterable instanceof Iterable) {
            for (Object o : (Iterable<?>) arrayOrIterable) {
            action.accept((E) o);
            }
            } else if (arrayOrIterable.getClass().isArray()) {
            int length = Array.getLength(arrayOrIterable);
            for (int i = 0; i < length; i++) {
            action.accept((E) Array.get(arrayOrIterable, i));
            }
            } else {
            throw new IllegalArgumentException("not an array nor iterable: " + arrayOrIterable.getClass());
            }
            }


            The second branch makes use of the java.reflect.Array class which provides helper methods (may be slow), to get the length of an array and the element at a given index.



            You may call it like this:



            int[] ints = {1, 2, 3, 4};
            forEach(ints, (Integer i) -> System.out.println(i));

            List<Integer> ints = Arrays.asList(1, 2, 3, 4);
            forEach(ints, (Integer i) -> System.out.println(i));


            Due to the nature of generics, this method may throw a ClassCastException, e.g. this call:



            int[] ints = {1, 2, 3, 4};
            forEach(ints, (String s) -> System.out.println(s));


            Would result in:



            java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String





            share|improve this answer


























            • I wouldn't dare to name the parameter arrayOrIterable since it's an Object and it might be anything

              – Andrew Tobilko
              yesterday






            • 1





              @AndrewTobilko Well this method only works with an array or an iterable, and will throw an exception for every other Object, so this should help as documentation that really one of those two types is expected

              – Lino
              yesterday











            • oh, I get you. It's a matter of personal preference/style, I guess.

              – Andrew Tobilko
              yesterday






            • 2





              @AndrewTobilko It really is something that is purely opinion based, best would be of course an extensive java-doc stating what can be passed into this method, what exceptions may be thrown etc.

              – Lino
              yesterday














            4












            4








            4







            You could write a helper method for this:



            @SuppressWarnings("unchecked")
            public static <E> void forEach(Object arrayOrIterable, Consumer<? super E> action) {
            Objects.requireNonNull(arrayOrIterable);
            if (arrayOrIterable instanceof Iterable) {
            for (Object o : (Iterable<?>) arrayOrIterable) {
            action.accept((E) o);
            }
            } else if (arrayOrIterable.getClass().isArray()) {
            int length = Array.getLength(arrayOrIterable);
            for (int i = 0; i < length; i++) {
            action.accept((E) Array.get(arrayOrIterable, i));
            }
            } else {
            throw new IllegalArgumentException("not an array nor iterable: " + arrayOrIterable.getClass());
            }
            }


            The second branch makes use of the java.reflect.Array class which provides helper methods (may be slow), to get the length of an array and the element at a given index.



            You may call it like this:



            int[] ints = {1, 2, 3, 4};
            forEach(ints, (Integer i) -> System.out.println(i));

            List<Integer> ints = Arrays.asList(1, 2, 3, 4);
            forEach(ints, (Integer i) -> System.out.println(i));


            Due to the nature of generics, this method may throw a ClassCastException, e.g. this call:



            int[] ints = {1, 2, 3, 4};
            forEach(ints, (String s) -> System.out.println(s));


            Would result in:



            java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String





            share|improve this answer















            You could write a helper method for this:



            @SuppressWarnings("unchecked")
            public static <E> void forEach(Object arrayOrIterable, Consumer<? super E> action) {
            Objects.requireNonNull(arrayOrIterable);
            if (arrayOrIterable instanceof Iterable) {
            for (Object o : (Iterable<?>) arrayOrIterable) {
            action.accept((E) o);
            }
            } else if (arrayOrIterable.getClass().isArray()) {
            int length = Array.getLength(arrayOrIterable);
            for (int i = 0; i < length; i++) {
            action.accept((E) Array.get(arrayOrIterable, i));
            }
            } else {
            throw new IllegalArgumentException("not an array nor iterable: " + arrayOrIterable.getClass());
            }
            }


            The second branch makes use of the java.reflect.Array class which provides helper methods (may be slow), to get the length of an array and the element at a given index.



            You may call it like this:



            int[] ints = {1, 2, 3, 4};
            forEach(ints, (Integer i) -> System.out.println(i));

            List<Integer> ints = Arrays.asList(1, 2, 3, 4);
            forEach(ints, (Integer i) -> System.out.println(i));


            Due to the nature of generics, this method may throw a ClassCastException, e.g. this call:



            int[] ints = {1, 2, 3, 4};
            forEach(ints, (String s) -> System.out.println(s));


            Would result in:



            java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited yesterday

























            answered yesterday









            LinoLino

            11.6k22344




            11.6k22344













            • I wouldn't dare to name the parameter arrayOrIterable since it's an Object and it might be anything

              – Andrew Tobilko
              yesterday






            • 1





              @AndrewTobilko Well this method only works with an array or an iterable, and will throw an exception for every other Object, so this should help as documentation that really one of those two types is expected

              – Lino
              yesterday











            • oh, I get you. It's a matter of personal preference/style, I guess.

              – Andrew Tobilko
              yesterday






            • 2





              @AndrewTobilko It really is something that is purely opinion based, best would be of course an extensive java-doc stating what can be passed into this method, what exceptions may be thrown etc.

              – Lino
              yesterday



















            • I wouldn't dare to name the parameter arrayOrIterable since it's an Object and it might be anything

              – Andrew Tobilko
              yesterday






            • 1





              @AndrewTobilko Well this method only works with an array or an iterable, and will throw an exception for every other Object, so this should help as documentation that really one of those two types is expected

              – Lino
              yesterday











            • oh, I get you. It's a matter of personal preference/style, I guess.

              – Andrew Tobilko
              yesterday






            • 2





              @AndrewTobilko It really is something that is purely opinion based, best would be of course an extensive java-doc stating what can be passed into this method, what exceptions may be thrown etc.

              – Lino
              yesterday

















            I wouldn't dare to name the parameter arrayOrIterable since it's an Object and it might be anything

            – Andrew Tobilko
            yesterday





            I wouldn't dare to name the parameter arrayOrIterable since it's an Object and it might be anything

            – Andrew Tobilko
            yesterday




            1




            1





            @AndrewTobilko Well this method only works with an array or an iterable, and will throw an exception for every other Object, so this should help as documentation that really one of those two types is expected

            – Lino
            yesterday





            @AndrewTobilko Well this method only works with an array or an iterable, and will throw an exception for every other Object, so this should help as documentation that really one of those two types is expected

            – Lino
            yesterday













            oh, I get you. It's a matter of personal preference/style, I guess.

            – Andrew Tobilko
            yesterday





            oh, I get you. It's a matter of personal preference/style, I guess.

            – Andrew Tobilko
            yesterday




            2




            2





            @AndrewTobilko It really is something that is purely opinion based, best would be of course an extensive java-doc stating what can be passed into this method, what exceptions may be thrown etc.

            – Lino
            yesterday





            @AndrewTobilko It really is something that is purely opinion based, best would be of course an extensive java-doc stating what can be passed into this method, what exceptions may be thrown etc.

            – Lino
            yesterday











            4














            You can check if object is array by using isArray() method from Class



            if (foo != null && (foo.getClass().isArray() || foo instanceof Collection<?>)){

            }


            Edit:



            In terms of iterating over this foo object, there is no simple solution. However you could try something like this:



            private void iterate(@NotNull Object foo) {
            if (foo instanceof Collection<?>) {
            for (Object o : ((Collection<?>) foo)) {
            chandleYourObject(o);
            }
            }

            if (foo.getClass().isArray()) {
            if (foo.getClass().isPrimitive()) {
            checkPrimitiveTypes(foo);
            }
            if (foo instanceof Object[]) {
            for (Object o : (Object[]) foo) {
            chandleYourObject(o);
            }
            }
            }
            }

            private void checkPrimitiveTypes(Object foo) {
            if (foo instanceof int[]) {
            for (int i : (int[]) foo) {

            }
            }
            //And the rest of primitive types
            }

            private void chandleYourObject(Object o ){
            //What you want to do with your object
            }





            share|improve this answer


























            • you can just check if foo instanceof Collection<?>. Shorter and more clear in my opinion. No nee to use Collection.class.isAssignableFrom. I've added partial answer because at first you didn't include isArray() method in your answer :)

              – Mershel
              yesterday













            • Though, I still believe that Collection.class.isAssignableFrom(fooClass) is more flexible than foo instanceof Collection because Collection.class could be any class at runtime (a dynamically obtained one, I mean)

              – Andrew Tobilko
              yesterday













            • Wouldn't that throw NPE when we would pass int[] i = null? I think that there will be no difference between Collection.class.isAssignableFrom(fooClass) and foo instanceof Collection<?>, that is just up to what you prefer and what is more readable for you ;)

              – Mershel
              yesterday
















            4














            You can check if object is array by using isArray() method from Class



            if (foo != null && (foo.getClass().isArray() || foo instanceof Collection<?>)){

            }


            Edit:



            In terms of iterating over this foo object, there is no simple solution. However you could try something like this:



            private void iterate(@NotNull Object foo) {
            if (foo instanceof Collection<?>) {
            for (Object o : ((Collection<?>) foo)) {
            chandleYourObject(o);
            }
            }

            if (foo.getClass().isArray()) {
            if (foo.getClass().isPrimitive()) {
            checkPrimitiveTypes(foo);
            }
            if (foo instanceof Object[]) {
            for (Object o : (Object[]) foo) {
            chandleYourObject(o);
            }
            }
            }
            }

            private void checkPrimitiveTypes(Object foo) {
            if (foo instanceof int[]) {
            for (int i : (int[]) foo) {

            }
            }
            //And the rest of primitive types
            }

            private void chandleYourObject(Object o ){
            //What you want to do with your object
            }





            share|improve this answer


























            • you can just check if foo instanceof Collection<?>. Shorter and more clear in my opinion. No nee to use Collection.class.isAssignableFrom. I've added partial answer because at first you didn't include isArray() method in your answer :)

              – Mershel
              yesterday













            • Though, I still believe that Collection.class.isAssignableFrom(fooClass) is more flexible than foo instanceof Collection because Collection.class could be any class at runtime (a dynamically obtained one, I mean)

              – Andrew Tobilko
              yesterday













            • Wouldn't that throw NPE when we would pass int[] i = null? I think that there will be no difference between Collection.class.isAssignableFrom(fooClass) and foo instanceof Collection<?>, that is just up to what you prefer and what is more readable for you ;)

              – Mershel
              yesterday














            4












            4








            4







            You can check if object is array by using isArray() method from Class



            if (foo != null && (foo.getClass().isArray() || foo instanceof Collection<?>)){

            }


            Edit:



            In terms of iterating over this foo object, there is no simple solution. However you could try something like this:



            private void iterate(@NotNull Object foo) {
            if (foo instanceof Collection<?>) {
            for (Object o : ((Collection<?>) foo)) {
            chandleYourObject(o);
            }
            }

            if (foo.getClass().isArray()) {
            if (foo.getClass().isPrimitive()) {
            checkPrimitiveTypes(foo);
            }
            if (foo instanceof Object[]) {
            for (Object o : (Object[]) foo) {
            chandleYourObject(o);
            }
            }
            }
            }

            private void checkPrimitiveTypes(Object foo) {
            if (foo instanceof int[]) {
            for (int i : (int[]) foo) {

            }
            }
            //And the rest of primitive types
            }

            private void chandleYourObject(Object o ){
            //What you want to do with your object
            }





            share|improve this answer















            You can check if object is array by using isArray() method from Class



            if (foo != null && (foo.getClass().isArray() || foo instanceof Collection<?>)){

            }


            Edit:



            In terms of iterating over this foo object, there is no simple solution. However you could try something like this:



            private void iterate(@NotNull Object foo) {
            if (foo instanceof Collection<?>) {
            for (Object o : ((Collection<?>) foo)) {
            chandleYourObject(o);
            }
            }

            if (foo.getClass().isArray()) {
            if (foo.getClass().isPrimitive()) {
            checkPrimitiveTypes(foo);
            }
            if (foo instanceof Object[]) {
            for (Object o : (Object[]) foo) {
            chandleYourObject(o);
            }
            }
            }
            }

            private void checkPrimitiveTypes(Object foo) {
            if (foo instanceof int[]) {
            for (int i : (int[]) foo) {

            }
            }
            //And the rest of primitive types
            }

            private void chandleYourObject(Object o ){
            //What you want to do with your object
            }






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited yesterday

























            answered yesterday









            MershelMershel

            280211




            280211













            • you can just check if foo instanceof Collection<?>. Shorter and more clear in my opinion. No nee to use Collection.class.isAssignableFrom. I've added partial answer because at first you didn't include isArray() method in your answer :)

              – Mershel
              yesterday













            • Though, I still believe that Collection.class.isAssignableFrom(fooClass) is more flexible than foo instanceof Collection because Collection.class could be any class at runtime (a dynamically obtained one, I mean)

              – Andrew Tobilko
              yesterday













            • Wouldn't that throw NPE when we would pass int[] i = null? I think that there will be no difference between Collection.class.isAssignableFrom(fooClass) and foo instanceof Collection<?>, that is just up to what you prefer and what is more readable for you ;)

              – Mershel
              yesterday



















            • you can just check if foo instanceof Collection<?>. Shorter and more clear in my opinion. No nee to use Collection.class.isAssignableFrom. I've added partial answer because at first you didn't include isArray() method in your answer :)

              – Mershel
              yesterday













            • Though, I still believe that Collection.class.isAssignableFrom(fooClass) is more flexible than foo instanceof Collection because Collection.class could be any class at runtime (a dynamically obtained one, I mean)

              – Andrew Tobilko
              yesterday













            • Wouldn't that throw NPE when we would pass int[] i = null? I think that there will be no difference between Collection.class.isAssignableFrom(fooClass) and foo instanceof Collection<?>, that is just up to what you prefer and what is more readable for you ;)

              – Mershel
              yesterday

















            you can just check if foo instanceof Collection<?>. Shorter and more clear in my opinion. No nee to use Collection.class.isAssignableFrom. I've added partial answer because at first you didn't include isArray() method in your answer :)

            – Mershel
            yesterday







            you can just check if foo instanceof Collection<?>. Shorter and more clear in my opinion. No nee to use Collection.class.isAssignableFrom. I've added partial answer because at first you didn't include isArray() method in your answer :)

            – Mershel
            yesterday















            Though, I still believe that Collection.class.isAssignableFrom(fooClass) is more flexible than foo instanceof Collection because Collection.class could be any class at runtime (a dynamically obtained one, I mean)

            – Andrew Tobilko
            yesterday







            Though, I still believe that Collection.class.isAssignableFrom(fooClass) is more flexible than foo instanceof Collection because Collection.class could be any class at runtime (a dynamically obtained one, I mean)

            – Andrew Tobilko
            yesterday















            Wouldn't that throw NPE when we would pass int[] i = null? I think that there will be no difference between Collection.class.isAssignableFrom(fooClass) and foo instanceof Collection<?>, that is just up to what you prefer and what is more readable for you ;)

            – Mershel
            yesterday





            Wouldn't that throw NPE when we would pass int[] i = null? I think that there will be no difference between Collection.class.isAssignableFrom(fooClass) and foo instanceof Collection<?>, that is just up to what you prefer and what is more readable for you ;)

            – Mershel
            yesterday











            4














            Arrays are Objects:



            https://docs.oracle.com/javase/specs/jls/se8/html/jls-10.html



            AbstractCollections also extend Object:



            https://docs.oracle.com/javase/8/docs/api/java/util/AbstractCollection.html



            So yes there is a common superclass, but unfortunately this isn't really going to help you.



            I would suggest your best bet is to use:



            List<> someList = Arrays.asList(sourceArray)


            This will convert your array into a collection that implements Iterable. You will of course need to work out if the initial object is an Array or a Collection in advance and only call the above if it is an array, here are some options for doing that:



            boolean isArray = myArray.getClass().isArray();
            boolean isCollection = Collection.class.isAssignableFrom(myList.getClass());





            share|improve this answer





















            • 4





              Arrays.asList() will sadly not work with primitive arrays

              – Lino
              yesterday






            • 1





              Agreed, but I'm making the assumption here that the OP is not using primitive arrays. If they are they could do something like Integer[] boxedInts = IntStream.of(ints).boxed().toArray(Integer[]::new); (Assuming they aren't using a byte[] array, in which case it gets more complex)

              – Ardesco
              yesterday






            • 1





              Arrays is a utility class that "contains various methods for manipulating arrays". It is not the superclass of arrays.

              – Solomon Ucko
              yesterday






            • 1





              True, updated the answer to point towards Java documentation that states Arrays are Objects instead,

              – Ardesco
              yesterday
















            4














            Arrays are Objects:



            https://docs.oracle.com/javase/specs/jls/se8/html/jls-10.html



            AbstractCollections also extend Object:



            https://docs.oracle.com/javase/8/docs/api/java/util/AbstractCollection.html



            So yes there is a common superclass, but unfortunately this isn't really going to help you.



            I would suggest your best bet is to use:



            List<> someList = Arrays.asList(sourceArray)


            This will convert your array into a collection that implements Iterable. You will of course need to work out if the initial object is an Array or a Collection in advance and only call the above if it is an array, here are some options for doing that:



            boolean isArray = myArray.getClass().isArray();
            boolean isCollection = Collection.class.isAssignableFrom(myList.getClass());





            share|improve this answer





















            • 4





              Arrays.asList() will sadly not work with primitive arrays

              – Lino
              yesterday






            • 1





              Agreed, but I'm making the assumption here that the OP is not using primitive arrays. If they are they could do something like Integer[] boxedInts = IntStream.of(ints).boxed().toArray(Integer[]::new); (Assuming they aren't using a byte[] array, in which case it gets more complex)

              – Ardesco
              yesterday






            • 1





              Arrays is a utility class that "contains various methods for manipulating arrays". It is not the superclass of arrays.

              – Solomon Ucko
              yesterday






            • 1





              True, updated the answer to point towards Java documentation that states Arrays are Objects instead,

              – Ardesco
              yesterday














            4












            4








            4







            Arrays are Objects:



            https://docs.oracle.com/javase/specs/jls/se8/html/jls-10.html



            AbstractCollections also extend Object:



            https://docs.oracle.com/javase/8/docs/api/java/util/AbstractCollection.html



            So yes there is a common superclass, but unfortunately this isn't really going to help you.



            I would suggest your best bet is to use:



            List<> someList = Arrays.asList(sourceArray)


            This will convert your array into a collection that implements Iterable. You will of course need to work out if the initial object is an Array or a Collection in advance and only call the above if it is an array, here are some options for doing that:



            boolean isArray = myArray.getClass().isArray();
            boolean isCollection = Collection.class.isAssignableFrom(myList.getClass());





            share|improve this answer















            Arrays are Objects:



            https://docs.oracle.com/javase/specs/jls/se8/html/jls-10.html



            AbstractCollections also extend Object:



            https://docs.oracle.com/javase/8/docs/api/java/util/AbstractCollection.html



            So yes there is a common superclass, but unfortunately this isn't really going to help you.



            I would suggest your best bet is to use:



            List<> someList = Arrays.asList(sourceArray)


            This will convert your array into a collection that implements Iterable. You will of course need to work out if the initial object is an Array or a Collection in advance and only call the above if it is an array, here are some options for doing that:



            boolean isArray = myArray.getClass().isArray();
            boolean isCollection = Collection.class.isAssignableFrom(myList.getClass());






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited yesterday

























            answered yesterday









            ArdescoArdesco

            5,4081744




            5,4081744








            • 4





              Arrays.asList() will sadly not work with primitive arrays

              – Lino
              yesterday






            • 1





              Agreed, but I'm making the assumption here that the OP is not using primitive arrays. If they are they could do something like Integer[] boxedInts = IntStream.of(ints).boxed().toArray(Integer[]::new); (Assuming they aren't using a byte[] array, in which case it gets more complex)

              – Ardesco
              yesterday






            • 1





              Arrays is a utility class that "contains various methods for manipulating arrays". It is not the superclass of arrays.

              – Solomon Ucko
              yesterday






            • 1





              True, updated the answer to point towards Java documentation that states Arrays are Objects instead,

              – Ardesco
              yesterday














            • 4





              Arrays.asList() will sadly not work with primitive arrays

              – Lino
              yesterday






            • 1





              Agreed, but I'm making the assumption here that the OP is not using primitive arrays. If they are they could do something like Integer[] boxedInts = IntStream.of(ints).boxed().toArray(Integer[]::new); (Assuming they aren't using a byte[] array, in which case it gets more complex)

              – Ardesco
              yesterday






            • 1





              Arrays is a utility class that "contains various methods for manipulating arrays". It is not the superclass of arrays.

              – Solomon Ucko
              yesterday






            • 1





              True, updated the answer to point towards Java documentation that states Arrays are Objects instead,

              – Ardesco
              yesterday








            4




            4





            Arrays.asList() will sadly not work with primitive arrays

            – Lino
            yesterday





            Arrays.asList() will sadly not work with primitive arrays

            – Lino
            yesterday




            1




            1





            Agreed, but I'm making the assumption here that the OP is not using primitive arrays. If they are they could do something like Integer[] boxedInts = IntStream.of(ints).boxed().toArray(Integer[]::new); (Assuming they aren't using a byte[] array, in which case it gets more complex)

            – Ardesco
            yesterday





            Agreed, but I'm making the assumption here that the OP is not using primitive arrays. If they are they could do something like Integer[] boxedInts = IntStream.of(ints).boxed().toArray(Integer[]::new); (Assuming they aren't using a byte[] array, in which case it gets more complex)

            – Ardesco
            yesterday




            1




            1





            Arrays is a utility class that "contains various methods for manipulating arrays". It is not the superclass of arrays.

            – Solomon Ucko
            yesterday





            Arrays is a utility class that "contains various methods for manipulating arrays". It is not the superclass of arrays.

            – Solomon Ucko
            yesterday




            1




            1





            True, updated the answer to point towards Java documentation that states Arrays are Objects instead,

            – Ardesco
            yesterday





            True, updated the answer to point towards Java documentation that states Arrays are Objects instead,

            – Ardesco
            yesterday


















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55588278%2fcan-i-write-a-for-loop-that-iterates-over-both-collections-and-arrays%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Couldn't open a raw socket. Error: Permission denied (13) (nmap)Is it possible to run networking commands...

            VNC viewer RFB protocol error: bad desktop size 0x0I Cannot Type the Key 'd' (lowercase) in VNC Viewer...

            Why not use the yoke to control yaw, as well as pitch and roll? Announcing the arrival of...