How to concatenate lists into one list












6















I have a list of values, some of which could be lists/collections or single values. In JavaScript notation it might look like:



const input = [1,2,[3,4], [5,6], 7];


and I want to get:



const concatenated = [1,2,3,4,5,6,7];


So I have this Java code:



      ArrayList<T> concatenated = new ArrayList<>();

for (T v : input) {
try{
concatenated.addAll((Collection) v);
}
catch (Exception e1){
try{
concatenated.addAll((List) v);
}
catch (Exception e2){
concatenated.add(v);
}
}

}


but that code seems pretty terrible to me. First I don't know if attempting to cast to List or Collection is sufficient - are there are other types I should attempt to cast to? Are there any errors I shouldn't ignore?



How to do this right?










share|improve this question




















  • 1





    fyi Java does not support mixed match type in list as you have in input, it can be like input = [[1],[2],[3,4], [5,6], [7]];

    – dkb
    3 hours ago













  • and there could be null values there (exception handling is for what otherwise)?

    – nullpointer
    3 hours ago











  • I think you can do this concatenated.addAll((Iterable) v); instead of try to cast to both Collection and List.

    – MrCholo
    3 hours ago






  • 2





    @MrCholo An array list does not have an overload for addAll with Iterable. The simplest interface you can use is Collection See here. The reason being that Iterable doesn't have to persist the data. It can be a read once, or even random in what data is returned. All it specifies is that you can iterate on it.

    – flakes
    2 hours ago
















6















I have a list of values, some of which could be lists/collections or single values. In JavaScript notation it might look like:



const input = [1,2,[3,4], [5,6], 7];


and I want to get:



const concatenated = [1,2,3,4,5,6,7];


So I have this Java code:



      ArrayList<T> concatenated = new ArrayList<>();

for (T v : input) {
try{
concatenated.addAll((Collection) v);
}
catch (Exception e1){
try{
concatenated.addAll((List) v);
}
catch (Exception e2){
concatenated.add(v);
}
}

}


but that code seems pretty terrible to me. First I don't know if attempting to cast to List or Collection is sufficient - are there are other types I should attempt to cast to? Are there any errors I shouldn't ignore?



How to do this right?










share|improve this question




















  • 1





    fyi Java does not support mixed match type in list as you have in input, it can be like input = [[1],[2],[3,4], [5,6], [7]];

    – dkb
    3 hours ago













  • and there could be null values there (exception handling is for what otherwise)?

    – nullpointer
    3 hours ago











  • I think you can do this concatenated.addAll((Iterable) v); instead of try to cast to both Collection and List.

    – MrCholo
    3 hours ago






  • 2





    @MrCholo An array list does not have an overload for addAll with Iterable. The simplest interface you can use is Collection See here. The reason being that Iterable doesn't have to persist the data. It can be a read once, or even random in what data is returned. All it specifies is that you can iterate on it.

    – flakes
    2 hours ago














6












6








6


1






I have a list of values, some of which could be lists/collections or single values. In JavaScript notation it might look like:



const input = [1,2,[3,4], [5,6], 7];


and I want to get:



const concatenated = [1,2,3,4,5,6,7];


So I have this Java code:



      ArrayList<T> concatenated = new ArrayList<>();

for (T v : input) {
try{
concatenated.addAll((Collection) v);
}
catch (Exception e1){
try{
concatenated.addAll((List) v);
}
catch (Exception e2){
concatenated.add(v);
}
}

}


but that code seems pretty terrible to me. First I don't know if attempting to cast to List or Collection is sufficient - are there are other types I should attempt to cast to? Are there any errors I shouldn't ignore?



How to do this right?










share|improve this question
















I have a list of values, some of which could be lists/collections or single values. In JavaScript notation it might look like:



const input = [1,2,[3,4], [5,6], 7];


and I want to get:



const concatenated = [1,2,3,4,5,6,7];


So I have this Java code:



      ArrayList<T> concatenated = new ArrayList<>();

for (T v : input) {
try{
concatenated.addAll((Collection) v);
}
catch (Exception e1){
try{
concatenated.addAll((List) v);
}
catch (Exception e2){
concatenated.add(v);
}
}

}


but that code seems pretty terrible to me. First I don't know if attempting to cast to List or Collection is sufficient - are there are other types I should attempt to cast to? Are there any errors I shouldn't ignore?



How to do this right?







java arraylist concatenation






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 1 hour ago







MrCholo

















asked 3 hours ago









MrCholoMrCholo

1,270931




1,270931








  • 1





    fyi Java does not support mixed match type in list as you have in input, it can be like input = [[1],[2],[3,4], [5,6], [7]];

    – dkb
    3 hours ago













  • and there could be null values there (exception handling is for what otherwise)?

    – nullpointer
    3 hours ago











  • I think you can do this concatenated.addAll((Iterable) v); instead of try to cast to both Collection and List.

    – MrCholo
    3 hours ago






  • 2





    @MrCholo An array list does not have an overload for addAll with Iterable. The simplest interface you can use is Collection See here. The reason being that Iterable doesn't have to persist the data. It can be a read once, or even random in what data is returned. All it specifies is that you can iterate on it.

    – flakes
    2 hours ago














  • 1





    fyi Java does not support mixed match type in list as you have in input, it can be like input = [[1],[2],[3,4], [5,6], [7]];

    – dkb
    3 hours ago













  • and there could be null values there (exception handling is for what otherwise)?

    – nullpointer
    3 hours ago











  • I think you can do this concatenated.addAll((Iterable) v); instead of try to cast to both Collection and List.

    – MrCholo
    3 hours ago






  • 2





    @MrCholo An array list does not have an overload for addAll with Iterable. The simplest interface you can use is Collection See here. The reason being that Iterable doesn't have to persist the data. It can be a read once, or even random in what data is returned. All it specifies is that you can iterate on it.

    – flakes
    2 hours ago








1




1





fyi Java does not support mixed match type in list as you have in input, it can be like input = [[1],[2],[3,4], [5,6], [7]];

– dkb
3 hours ago







fyi Java does not support mixed match type in list as you have in input, it can be like input = [[1],[2],[3,4], [5,6], [7]];

– dkb
3 hours ago















and there could be null values there (exception handling is for what otherwise)?

– nullpointer
3 hours ago





and there could be null values there (exception handling is for what otherwise)?

– nullpointer
3 hours ago













I think you can do this concatenated.addAll((Iterable) v); instead of try to cast to both Collection and List.

– MrCholo
3 hours ago





I think you can do this concatenated.addAll((Iterable) v); instead of try to cast to both Collection and List.

– MrCholo
3 hours ago




2




2





@MrCholo An array list does not have an overload for addAll with Iterable. The simplest interface you can use is Collection See here. The reason being that Iterable doesn't have to persist the data. It can be a read once, or even random in what data is returned. All it specifies is that you can iterate on it.

– flakes
2 hours ago





@MrCholo An array list does not have an overload for addAll with Iterable. The simplest interface you can use is Collection See here. The reason being that Iterable doesn't have to persist the data. It can be a read once, or even random in what data is returned. All it specifies is that you can iterate on it.

– flakes
2 hours ago












3 Answers
3






active

oldest

votes


















7














The code doesn't need Exception handling as such unless there are null values in the lists. It should be sufficient though in your case to just cast basis of instanceOf as:



// Edit: Since the type of the input `Collection` is not bound strictly
List<Object> flatten(Collection<?> input) {
List<Object> concatenated = new ArrayList<>();
for (Object v : input) {
if (v instanceof Collection) {
concatenated.addAll(flatten((Collection<?>) v));
} else {
concatenated.add(v);
}
}
return concatenated;
}


using it further on jshell gives me this output:



jshell> List<Object> list = List.of(1,2,List.of(3,4),List.of(5,6),7) 
list ==> [1, 2, [3, 4], [5, 6], 7]

jshell> concatenateList(list)
$3 ==> [1, 2, 3, 4, 5, 6, 7]


:






share|improve this answer


























  • yeah but what about Collection? Can you use instanceof on Iterable? Collection and List both implement Iterable, so that might work

    – MrCholo
    3 hours ago






  • 1





    @MrCholo null is a valid argument to instanceof. it will always return false. And an ArrayList can accept null as an input to add.

    – flakes
    2 hours ago






  • 2





    I think a nice addition to this solution would be to make it recursive. ie concatenated.addAll(concatenateList((List<T>) v)) This way you can handle multiple levels of nesting. A better name on this method might be flatten

    – flakes
    2 hours ago








  • 1





    @MrCholo List extends Collection

    – nullpointer
    2 hours ago






  • 1





    @nullpointer It's an interesting problem! I have tried to solve this problem before (when dealing with examining JSON data without having a schema ahead of time) and I don't think Java has a good model for dealing with this. The root problem is that a basic Collection or List or Map interface does not account for nested hierarchies of data when specializing the container. Other languages combat this problem differently, say through the use of pattern matching rather than strict class matching. A good example of tackling this is in Python's new type hints system.

    – flakes
    1 hour ago



















2














Use of Exceptions to control application flow/business logic is an anti-pattern. You can read more about it here, here and here.



Regarding storing different types of elements in Collections could be difficult to debug and maintain. You can write your own wrapper and encapsulate the handling of it from usage. You can refer this for an inspiration.






share|improve this answer































    1














    As others have mentioned, using exceptions for control flow is not ideal. You can instead use the instanceof operator to test if an element is a Collection. The answer by nullpointer shows a good example of this. If you want an more generic option you could also do something like:



    import java.lang.reflect.Array;
    import java.util.Arrays;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.stream.IntStream;

    public static <E> List<E> deepFlatten(final Iterable<?> iterable, final Class<E> type) {
    if (type.isPrimitive() || type.isArray() || Iterable.class.isAssignableFrom(type)) {
    throw new IllegalArgumentException(
    "type must not denote a primitive, array, or java.lang.Iterable type: " + type);
    }
    final List<E> result = new ArrayList<>();
    for (final Object element : iterable) {

    if (element instanceof Iterable<?>) {
    result.addAll(deepFlatten((Iterable<?>) element, type)); // recursion

    } else if (element != null && element.getClass().isArray()) {

    if (element instanceof Object) {
    result.addAll(deepFlatten(Arrays.asList((Object) element), type)); // recursion
    } else { // primitive array
    final Iterable<?> itrArray = IntStream.range(0, Array.getLength(element))
    .mapToObj(index -> Array.get(element, index))::iterator; // method reference
    result.addAll(deepFlatten(itrArray, type)); // recursion
    }

    } else {
    /*
    * Will throw ClassCastException if any element is not an instance
    * of "type". You could also throw a NullPointerException here if
    * you don't want to allow null elements.
    */
    result.add(type.cast(element));
    }

    }
    return result;
    }


    This also handles "embedded" arrays, as well as Iterables, through recursion. Note it doesn't handle Maps because of the ambiguity; should we flatten the keys or the values—or both?



    Calling the above with:



    Iterable<?> iterable = List.of(
    "A", "B", "C", "D",
    List.of("E", "F", List.of("G", "H"), "I", "J"),
    "K",
    new String{"L", "M", "N", "O", "P"},
    new String{{"Q", "R"}, {"S", "T"}, {"U"}, {"V"}},
    new Object{"W", "X"},
    "Y", "Z"
    );
    List<String> flattened = deepFlatten(iterable, String.class);
    System.out.println(flattened);


    Gave me:



    [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z]


    Note that the letters are in order because Lists and arrays have guaranteed iteration orders. If your Iterable contained a Set the result of the deepFlatten may not be in the same order each time.






    share|improve this answer

























      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%2f54624265%2fhow-to-concatenate-lists-into-one-list%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      3 Answers
      3






      active

      oldest

      votes








      3 Answers
      3






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      7














      The code doesn't need Exception handling as such unless there are null values in the lists. It should be sufficient though in your case to just cast basis of instanceOf as:



      // Edit: Since the type of the input `Collection` is not bound strictly
      List<Object> flatten(Collection<?> input) {
      List<Object> concatenated = new ArrayList<>();
      for (Object v : input) {
      if (v instanceof Collection) {
      concatenated.addAll(flatten((Collection<?>) v));
      } else {
      concatenated.add(v);
      }
      }
      return concatenated;
      }


      using it further on jshell gives me this output:



      jshell> List<Object> list = List.of(1,2,List.of(3,4),List.of(5,6),7) 
      list ==> [1, 2, [3, 4], [5, 6], 7]

      jshell> concatenateList(list)
      $3 ==> [1, 2, 3, 4, 5, 6, 7]


      :






      share|improve this answer


























      • yeah but what about Collection? Can you use instanceof on Iterable? Collection and List both implement Iterable, so that might work

        – MrCholo
        3 hours ago






      • 1





        @MrCholo null is a valid argument to instanceof. it will always return false. And an ArrayList can accept null as an input to add.

        – flakes
        2 hours ago






      • 2





        I think a nice addition to this solution would be to make it recursive. ie concatenated.addAll(concatenateList((List<T>) v)) This way you can handle multiple levels of nesting. A better name on this method might be flatten

        – flakes
        2 hours ago








      • 1





        @MrCholo List extends Collection

        – nullpointer
        2 hours ago






      • 1





        @nullpointer It's an interesting problem! I have tried to solve this problem before (when dealing with examining JSON data without having a schema ahead of time) and I don't think Java has a good model for dealing with this. The root problem is that a basic Collection or List or Map interface does not account for nested hierarchies of data when specializing the container. Other languages combat this problem differently, say through the use of pattern matching rather than strict class matching. A good example of tackling this is in Python's new type hints system.

        – flakes
        1 hour ago
















      7














      The code doesn't need Exception handling as such unless there are null values in the lists. It should be sufficient though in your case to just cast basis of instanceOf as:



      // Edit: Since the type of the input `Collection` is not bound strictly
      List<Object> flatten(Collection<?> input) {
      List<Object> concatenated = new ArrayList<>();
      for (Object v : input) {
      if (v instanceof Collection) {
      concatenated.addAll(flatten((Collection<?>) v));
      } else {
      concatenated.add(v);
      }
      }
      return concatenated;
      }


      using it further on jshell gives me this output:



      jshell> List<Object> list = List.of(1,2,List.of(3,4),List.of(5,6),7) 
      list ==> [1, 2, [3, 4], [5, 6], 7]

      jshell> concatenateList(list)
      $3 ==> [1, 2, 3, 4, 5, 6, 7]


      :






      share|improve this answer


























      • yeah but what about Collection? Can you use instanceof on Iterable? Collection and List both implement Iterable, so that might work

        – MrCholo
        3 hours ago






      • 1





        @MrCholo null is a valid argument to instanceof. it will always return false. And an ArrayList can accept null as an input to add.

        – flakes
        2 hours ago






      • 2





        I think a nice addition to this solution would be to make it recursive. ie concatenated.addAll(concatenateList((List<T>) v)) This way you can handle multiple levels of nesting. A better name on this method might be flatten

        – flakes
        2 hours ago








      • 1





        @MrCholo List extends Collection

        – nullpointer
        2 hours ago






      • 1





        @nullpointer It's an interesting problem! I have tried to solve this problem before (when dealing with examining JSON data without having a schema ahead of time) and I don't think Java has a good model for dealing with this. The root problem is that a basic Collection or List or Map interface does not account for nested hierarchies of data when specializing the container. Other languages combat this problem differently, say through the use of pattern matching rather than strict class matching. A good example of tackling this is in Python's new type hints system.

        – flakes
        1 hour ago














      7












      7








      7







      The code doesn't need Exception handling as such unless there are null values in the lists. It should be sufficient though in your case to just cast basis of instanceOf as:



      // Edit: Since the type of the input `Collection` is not bound strictly
      List<Object> flatten(Collection<?> input) {
      List<Object> concatenated = new ArrayList<>();
      for (Object v : input) {
      if (v instanceof Collection) {
      concatenated.addAll(flatten((Collection<?>) v));
      } else {
      concatenated.add(v);
      }
      }
      return concatenated;
      }


      using it further on jshell gives me this output:



      jshell> List<Object> list = List.of(1,2,List.of(3,4),List.of(5,6),7) 
      list ==> [1, 2, [3, 4], [5, 6], 7]

      jshell> concatenateList(list)
      $3 ==> [1, 2, 3, 4, 5, 6, 7]


      :






      share|improve this answer















      The code doesn't need Exception handling as such unless there are null values in the lists. It should be sufficient though in your case to just cast basis of instanceOf as:



      // Edit: Since the type of the input `Collection` is not bound strictly
      List<Object> flatten(Collection<?> input) {
      List<Object> concatenated = new ArrayList<>();
      for (Object v : input) {
      if (v instanceof Collection) {
      concatenated.addAll(flatten((Collection<?>) v));
      } else {
      concatenated.add(v);
      }
      }
      return concatenated;
      }


      using it further on jshell gives me this output:



      jshell> List<Object> list = List.of(1,2,List.of(3,4),List.of(5,6),7) 
      list ==> [1, 2, [3, 4], [5, 6], 7]

      jshell> concatenateList(list)
      $3 ==> [1, 2, 3, 4, 5, 6, 7]


      :







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited 2 hours ago

























      answered 3 hours ago









      nullpointernullpointer

      48.8k11101196




      48.8k11101196













      • yeah but what about Collection? Can you use instanceof on Iterable? Collection and List both implement Iterable, so that might work

        – MrCholo
        3 hours ago






      • 1





        @MrCholo null is a valid argument to instanceof. it will always return false. And an ArrayList can accept null as an input to add.

        – flakes
        2 hours ago






      • 2





        I think a nice addition to this solution would be to make it recursive. ie concatenated.addAll(concatenateList((List<T>) v)) This way you can handle multiple levels of nesting. A better name on this method might be flatten

        – flakes
        2 hours ago








      • 1





        @MrCholo List extends Collection

        – nullpointer
        2 hours ago






      • 1





        @nullpointer It's an interesting problem! I have tried to solve this problem before (when dealing with examining JSON data without having a schema ahead of time) and I don't think Java has a good model for dealing with this. The root problem is that a basic Collection or List or Map interface does not account for nested hierarchies of data when specializing the container. Other languages combat this problem differently, say through the use of pattern matching rather than strict class matching. A good example of tackling this is in Python's new type hints system.

        – flakes
        1 hour ago



















      • yeah but what about Collection? Can you use instanceof on Iterable? Collection and List both implement Iterable, so that might work

        – MrCholo
        3 hours ago






      • 1





        @MrCholo null is a valid argument to instanceof. it will always return false. And an ArrayList can accept null as an input to add.

        – flakes
        2 hours ago






      • 2





        I think a nice addition to this solution would be to make it recursive. ie concatenated.addAll(concatenateList((List<T>) v)) This way you can handle multiple levels of nesting. A better name on this method might be flatten

        – flakes
        2 hours ago








      • 1





        @MrCholo List extends Collection

        – nullpointer
        2 hours ago






      • 1





        @nullpointer It's an interesting problem! I have tried to solve this problem before (when dealing with examining JSON data without having a schema ahead of time) and I don't think Java has a good model for dealing with this. The root problem is that a basic Collection or List or Map interface does not account for nested hierarchies of data when specializing the container. Other languages combat this problem differently, say through the use of pattern matching rather than strict class matching. A good example of tackling this is in Python's new type hints system.

        – flakes
        1 hour ago

















      yeah but what about Collection? Can you use instanceof on Iterable? Collection and List both implement Iterable, so that might work

      – MrCholo
      3 hours ago





      yeah but what about Collection? Can you use instanceof on Iterable? Collection and List both implement Iterable, so that might work

      – MrCholo
      3 hours ago




      1




      1





      @MrCholo null is a valid argument to instanceof. it will always return false. And an ArrayList can accept null as an input to add.

      – flakes
      2 hours ago





      @MrCholo null is a valid argument to instanceof. it will always return false. And an ArrayList can accept null as an input to add.

      – flakes
      2 hours ago




      2




      2





      I think a nice addition to this solution would be to make it recursive. ie concatenated.addAll(concatenateList((List<T>) v)) This way you can handle multiple levels of nesting. A better name on this method might be flatten

      – flakes
      2 hours ago







      I think a nice addition to this solution would be to make it recursive. ie concatenated.addAll(concatenateList((List<T>) v)) This way you can handle multiple levels of nesting. A better name on this method might be flatten

      – flakes
      2 hours ago






      1




      1





      @MrCholo List extends Collection

      – nullpointer
      2 hours ago





      @MrCholo List extends Collection

      – nullpointer
      2 hours ago




      1




      1





      @nullpointer It's an interesting problem! I have tried to solve this problem before (when dealing with examining JSON data without having a schema ahead of time) and I don't think Java has a good model for dealing with this. The root problem is that a basic Collection or List or Map interface does not account for nested hierarchies of data when specializing the container. Other languages combat this problem differently, say through the use of pattern matching rather than strict class matching. A good example of tackling this is in Python's new type hints system.

      – flakes
      1 hour ago





      @nullpointer It's an interesting problem! I have tried to solve this problem before (when dealing with examining JSON data without having a schema ahead of time) and I don't think Java has a good model for dealing with this. The root problem is that a basic Collection or List or Map interface does not account for nested hierarchies of data when specializing the container. Other languages combat this problem differently, say through the use of pattern matching rather than strict class matching. A good example of tackling this is in Python's new type hints system.

      – flakes
      1 hour ago













      2














      Use of Exceptions to control application flow/business logic is an anti-pattern. You can read more about it here, here and here.



      Regarding storing different types of elements in Collections could be difficult to debug and maintain. You can write your own wrapper and encapsulate the handling of it from usage. You can refer this for an inspiration.






      share|improve this answer




























        2














        Use of Exceptions to control application flow/business logic is an anti-pattern. You can read more about it here, here and here.



        Regarding storing different types of elements in Collections could be difficult to debug and maintain. You can write your own wrapper and encapsulate the handling of it from usage. You can refer this for an inspiration.






        share|improve this answer


























          2












          2








          2







          Use of Exceptions to control application flow/business logic is an anti-pattern. You can read more about it here, here and here.



          Regarding storing different types of elements in Collections could be difficult to debug and maintain. You can write your own wrapper and encapsulate the handling of it from usage. You can refer this for an inspiration.






          share|improve this answer













          Use of Exceptions to control application flow/business logic is an anti-pattern. You can read more about it here, here and here.



          Regarding storing different types of elements in Collections could be difficult to debug and maintain. You can write your own wrapper and encapsulate the handling of it from usage. You can refer this for an inspiration.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered 3 hours ago









          Ashutosh VaidyaAshutosh Vaidya

          539




          539























              1














              As others have mentioned, using exceptions for control flow is not ideal. You can instead use the instanceof operator to test if an element is a Collection. The answer by nullpointer shows a good example of this. If you want an more generic option you could also do something like:



              import java.lang.reflect.Array;
              import java.util.Arrays;
              import java.util.ArrayList;
              import java.util.List;
              import java.util.stream.IntStream;

              public static <E> List<E> deepFlatten(final Iterable<?> iterable, final Class<E> type) {
              if (type.isPrimitive() || type.isArray() || Iterable.class.isAssignableFrom(type)) {
              throw new IllegalArgumentException(
              "type must not denote a primitive, array, or java.lang.Iterable type: " + type);
              }
              final List<E> result = new ArrayList<>();
              for (final Object element : iterable) {

              if (element instanceof Iterable<?>) {
              result.addAll(deepFlatten((Iterable<?>) element, type)); // recursion

              } else if (element != null && element.getClass().isArray()) {

              if (element instanceof Object) {
              result.addAll(deepFlatten(Arrays.asList((Object) element), type)); // recursion
              } else { // primitive array
              final Iterable<?> itrArray = IntStream.range(0, Array.getLength(element))
              .mapToObj(index -> Array.get(element, index))::iterator; // method reference
              result.addAll(deepFlatten(itrArray, type)); // recursion
              }

              } else {
              /*
              * Will throw ClassCastException if any element is not an instance
              * of "type". You could also throw a NullPointerException here if
              * you don't want to allow null elements.
              */
              result.add(type.cast(element));
              }

              }
              return result;
              }


              This also handles "embedded" arrays, as well as Iterables, through recursion. Note it doesn't handle Maps because of the ambiguity; should we flatten the keys or the values—or both?



              Calling the above with:



              Iterable<?> iterable = List.of(
              "A", "B", "C", "D",
              List.of("E", "F", List.of("G", "H"), "I", "J"),
              "K",
              new String{"L", "M", "N", "O", "P"},
              new String{{"Q", "R"}, {"S", "T"}, {"U"}, {"V"}},
              new Object{"W", "X"},
              "Y", "Z"
              );
              List<String> flattened = deepFlatten(iterable, String.class);
              System.out.println(flattened);


              Gave me:



              [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z]


              Note that the letters are in order because Lists and arrays have guaranteed iteration orders. If your Iterable contained a Set the result of the deepFlatten may not be in the same order each time.






              share|improve this answer






























                1














                As others have mentioned, using exceptions for control flow is not ideal. You can instead use the instanceof operator to test if an element is a Collection. The answer by nullpointer shows a good example of this. If you want an more generic option you could also do something like:



                import java.lang.reflect.Array;
                import java.util.Arrays;
                import java.util.ArrayList;
                import java.util.List;
                import java.util.stream.IntStream;

                public static <E> List<E> deepFlatten(final Iterable<?> iterable, final Class<E> type) {
                if (type.isPrimitive() || type.isArray() || Iterable.class.isAssignableFrom(type)) {
                throw new IllegalArgumentException(
                "type must not denote a primitive, array, or java.lang.Iterable type: " + type);
                }
                final List<E> result = new ArrayList<>();
                for (final Object element : iterable) {

                if (element instanceof Iterable<?>) {
                result.addAll(deepFlatten((Iterable<?>) element, type)); // recursion

                } else if (element != null && element.getClass().isArray()) {

                if (element instanceof Object) {
                result.addAll(deepFlatten(Arrays.asList((Object) element), type)); // recursion
                } else { // primitive array
                final Iterable<?> itrArray = IntStream.range(0, Array.getLength(element))
                .mapToObj(index -> Array.get(element, index))::iterator; // method reference
                result.addAll(deepFlatten(itrArray, type)); // recursion
                }

                } else {
                /*
                * Will throw ClassCastException if any element is not an instance
                * of "type". You could also throw a NullPointerException here if
                * you don't want to allow null elements.
                */
                result.add(type.cast(element));
                }

                }
                return result;
                }


                This also handles "embedded" arrays, as well as Iterables, through recursion. Note it doesn't handle Maps because of the ambiguity; should we flatten the keys or the values—or both?



                Calling the above with:



                Iterable<?> iterable = List.of(
                "A", "B", "C", "D",
                List.of("E", "F", List.of("G", "H"), "I", "J"),
                "K",
                new String{"L", "M", "N", "O", "P"},
                new String{{"Q", "R"}, {"S", "T"}, {"U"}, {"V"}},
                new Object{"W", "X"},
                "Y", "Z"
                );
                List<String> flattened = deepFlatten(iterable, String.class);
                System.out.println(flattened);


                Gave me:



                [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z]


                Note that the letters are in order because Lists and arrays have guaranteed iteration orders. If your Iterable contained a Set the result of the deepFlatten may not be in the same order each time.






                share|improve this answer




























                  1












                  1








                  1







                  As others have mentioned, using exceptions for control flow is not ideal. You can instead use the instanceof operator to test if an element is a Collection. The answer by nullpointer shows a good example of this. If you want an more generic option you could also do something like:



                  import java.lang.reflect.Array;
                  import java.util.Arrays;
                  import java.util.ArrayList;
                  import java.util.List;
                  import java.util.stream.IntStream;

                  public static <E> List<E> deepFlatten(final Iterable<?> iterable, final Class<E> type) {
                  if (type.isPrimitive() || type.isArray() || Iterable.class.isAssignableFrom(type)) {
                  throw new IllegalArgumentException(
                  "type must not denote a primitive, array, or java.lang.Iterable type: " + type);
                  }
                  final List<E> result = new ArrayList<>();
                  for (final Object element : iterable) {

                  if (element instanceof Iterable<?>) {
                  result.addAll(deepFlatten((Iterable<?>) element, type)); // recursion

                  } else if (element != null && element.getClass().isArray()) {

                  if (element instanceof Object) {
                  result.addAll(deepFlatten(Arrays.asList((Object) element), type)); // recursion
                  } else { // primitive array
                  final Iterable<?> itrArray = IntStream.range(0, Array.getLength(element))
                  .mapToObj(index -> Array.get(element, index))::iterator; // method reference
                  result.addAll(deepFlatten(itrArray, type)); // recursion
                  }

                  } else {
                  /*
                  * Will throw ClassCastException if any element is not an instance
                  * of "type". You could also throw a NullPointerException here if
                  * you don't want to allow null elements.
                  */
                  result.add(type.cast(element));
                  }

                  }
                  return result;
                  }


                  This also handles "embedded" arrays, as well as Iterables, through recursion. Note it doesn't handle Maps because of the ambiguity; should we flatten the keys or the values—or both?



                  Calling the above with:



                  Iterable<?> iterable = List.of(
                  "A", "B", "C", "D",
                  List.of("E", "F", List.of("G", "H"), "I", "J"),
                  "K",
                  new String{"L", "M", "N", "O", "P"},
                  new String{{"Q", "R"}, {"S", "T"}, {"U"}, {"V"}},
                  new Object{"W", "X"},
                  "Y", "Z"
                  );
                  List<String> flattened = deepFlatten(iterable, String.class);
                  System.out.println(flattened);


                  Gave me:



                  [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z]


                  Note that the letters are in order because Lists and arrays have guaranteed iteration orders. If your Iterable contained a Set the result of the deepFlatten may not be in the same order each time.






                  share|improve this answer















                  As others have mentioned, using exceptions for control flow is not ideal. You can instead use the instanceof operator to test if an element is a Collection. The answer by nullpointer shows a good example of this. If you want an more generic option you could also do something like:



                  import java.lang.reflect.Array;
                  import java.util.Arrays;
                  import java.util.ArrayList;
                  import java.util.List;
                  import java.util.stream.IntStream;

                  public static <E> List<E> deepFlatten(final Iterable<?> iterable, final Class<E> type) {
                  if (type.isPrimitive() || type.isArray() || Iterable.class.isAssignableFrom(type)) {
                  throw new IllegalArgumentException(
                  "type must not denote a primitive, array, or java.lang.Iterable type: " + type);
                  }
                  final List<E> result = new ArrayList<>();
                  for (final Object element : iterable) {

                  if (element instanceof Iterable<?>) {
                  result.addAll(deepFlatten((Iterable<?>) element, type)); // recursion

                  } else if (element != null && element.getClass().isArray()) {

                  if (element instanceof Object) {
                  result.addAll(deepFlatten(Arrays.asList((Object) element), type)); // recursion
                  } else { // primitive array
                  final Iterable<?> itrArray = IntStream.range(0, Array.getLength(element))
                  .mapToObj(index -> Array.get(element, index))::iterator; // method reference
                  result.addAll(deepFlatten(itrArray, type)); // recursion
                  }

                  } else {
                  /*
                  * Will throw ClassCastException if any element is not an instance
                  * of "type". You could also throw a NullPointerException here if
                  * you don't want to allow null elements.
                  */
                  result.add(type.cast(element));
                  }

                  }
                  return result;
                  }


                  This also handles "embedded" arrays, as well as Iterables, through recursion. Note it doesn't handle Maps because of the ambiguity; should we flatten the keys or the values—or both?



                  Calling the above with:



                  Iterable<?> iterable = List.of(
                  "A", "B", "C", "D",
                  List.of("E", "F", List.of("G", "H"), "I", "J"),
                  "K",
                  new String{"L", "M", "N", "O", "P"},
                  new String{{"Q", "R"}, {"S", "T"}, {"U"}, {"V"}},
                  new Object{"W", "X"},
                  "Y", "Z"
                  );
                  List<String> flattened = deepFlatten(iterable, String.class);
                  System.out.println(flattened);


                  Gave me:



                  [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z]


                  Note that the letters are in order because Lists and arrays have guaranteed iteration orders. If your Iterable contained a Set the result of the deepFlatten may not be in the same order each time.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited 53 mins ago

























                  answered 1 hour ago









                  SlawSlaw

                  8,04231033




                  8,04231033






























                      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%2f54624265%2fhow-to-concatenate-lists-into-one-list%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

                      Liste der Baudenkmäler in Partschins

                      Sámuel Mokry

                      Valadolido