2

I have two arraylists

    ArrayList<File> filesImage= new ArrayList<File>();
    ArrayList<File> filesBox= new ArrayList<File>();

I want to merge into third arraylist like this

    ArrayList<File[]> combinedFiles=new ArrayList<File[]>();

How can I do this? Output should be like:

   [[ first object of filesImage, first object of filesBox],[second Object],[]]
6
  • 1
    @ΦXocę웃Пepeúpaツ No that add's in linear way. Not as a individual array. Commented Apr 25, 2017 at 10:36
  • What have you tried so far? @ΦXocę웃Пepeúpaツ addAll would add all entries from one collection to the other, not "zip" them into pairs in arrays. Commented Apr 25, 2017 at 10:36
  • How about iterating over the lists simultaneously and building and adding the element array for each iteration? Or yet better, why don't you build a small object that contains both file references to make it less error-prone and easier to understand? Commented Apr 25, 2017 at 10:40
  • 3
    As an aside, I'd probably use a Map for this instead, it expresses the structure of your data more accurately. But the basic solution is the same in both cases: iterate across the two lists in parallel and pick one element from each in every step. Commented Apr 25, 2017 at 10:40
  • @biziclop i tried with map its working but not the way i want it. Its giving a key-value pairs. I want to store path of 2 files in array of a arraylist Commented Apr 25, 2017 at 10:46

6 Answers 6

5

Given that the two arrays are of equal length that you wish to combine, i'd personally do something like this.

List<File[]> combinedFiles= new ArrayList<File[]>();

for(int i = 0; i < filesBox.size(); i++){
    combinedFiles.add(new File[] {filesImage.get(i), filesBox.get(i)});
}

Apologies if my methods are incorrect, its been a while since i've programmed in java.

Sign up to request clarification or add additional context in comments.

1 Comment

I think the only thing that's missing is to check that the two arraylists are the same size.
5

First, I'd create a class that holds the file references, e.g. like this:

class FileElement {
  File image;
  File box;
}

Then I'd create a list of those instead of arrays:

List<FileElement> combinedFiles = ...;

Then I'd iterate over both lists simultaneously:

Iterator<File> imgItr = filesImages.iterator();
Iterator<File> boxItr = filesBox.iterator();

//This assumes it's ok if both lists have different sizes. 
//If it isn't you could try && instead, i.e. stop once you'd miss an image or a box
while( imgItr.hasNext() || boxItr.hasNext() ) {
   FileElement e = ...;

   if( imgItr.hasNext() ) { 
     e.image = imgItr.next();
   }

   if( boxItr.hasNext() ) { 
     e.box= boxItr.next();
   }

   combinedFiles.add( e );
}

3 Comments

Encapsulating things in a class is useful if additional functionality is added to it, otherwise a 2-element array seems just fine. No need to invent more classes unless necessary. I wish Java had a Pair class...
@G_H there are reasons why there is no pair class and one is that in most cases it's better give provide names for the elements inside a pair (as an example they mention 2d points which are not just 2 int elements but rather provide names like x and y). Using a specific class helps making the code easier to read since if in the future you read combinedFiles.get(0)[0] you'll not know what that file is meant to be, but if you read combinedFiles.get(0).image you know that it's meant to be an image file.
Good point, it's likely the ArrayList with arrays is gonna be passed onto some other context rather than used locally, or it wouldn't really be necessary to begin with.
2

Assuming that the two lists are of equal length, here is a solution using Java8 streams and zip().

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;


public class Demo {

    public static void main( String[] args ) {
        List<String> filesImage = Arrays.asList("a","b","c");
        List<String> filesBox   = Arrays.asList("1","2", "3");

        List<String[]> result = zip(filesImage.stream(), filesBox.stream(), (a,b) -> new String[] {a,b}).collect( Collectors.toList() );

        for ( String[] e : result ) {
            System.out.println( Arrays.asList(e) );
        }
    }

    public static <A, B, C> Stream<C> zip(Stream<A> streamA, Stream<B> streamB, BiFunction<A, B, C> zipper) {
        final Iterator<A> iteratorA = streamA.iterator();
        final Iterator<B> iteratorB = streamB.iterator();
        final Iterator<C> iteratorC = new Iterator<C>() {
            @Override
            public boolean hasNext() {
                return iteratorA.hasNext() && iteratorB.hasNext();
            }

            @Override
            public C next() {
                return zipper.apply(iteratorA.next(), iteratorB.next());
            }
        };
        final boolean parallel = streamA.isParallel() || streamB.isParallel();
        return iteratorToFiniteStream(iteratorC, parallel);
    }

    public static <T> Stream<T> iteratorToFiniteStream( Iterator<T> iterator, boolean parallel) {
        final Iterable<T> iterable = () -> iterator;
        return StreamSupport.stream(iterable.spliterator(), parallel);
    }
}

I borrowed the implementation of zip from Karol Krol here. Zip is the name from the functional world for this pattern of combining two lists in this manner. Also note that while Demo uses String's instead of File, the concept remains exactly the same.

3 Comments

Having a generic zip operation is certainly nice (and I wonder why it's not available in Java SE's API) but I think this might be a bit overkill for OP's use case, and possibly over their head given the question asked.
@G_H it is useful for documenting the functional approach for others who come across the question
That is true. My first thought was "oh, a zip" and was a bit surprised Java doesn't have it out-of-the-box. Seems a fairly fundamental FP operation.
1

Normally I wouldn't answer a question where OP doesn't show what they've tried, but since I'm seeing a flood of incorrect answers and interpretations...

List<File> filesImage= new ArrayList<File>();
List<File> filesBox= new ArrayList<File>();
List<File[]> combinedFiles=new ArrayList<File[]>();
for (int i = 0; i < filesImage.size(); ++i) {
    File[] temp = new File[2];
    temp[0] = filesImage.get(i);
    temp[1] = filesBox.get(i);
    combinedFiles.add(temp);
}

Something like this is known as "zipping" in functional programming, by the way. I'd suggest a solution with Java 8 lambdas, but there doesn't seem to be a zip function in Java SE and the above is quite simple.

Comments

0

Should work similar to this pseudo code

List<File[]> merge = new ArrayList<>();

for(int i=0;i<filesImage.legth&&i<filesBox.length;i++{
    merge.add(new File[]{i<filesImage.legth?filesImage[i]:null,i<filesBox.legth?filesBox[i]});
}

Comments

0

You can use function toArray of List to make array.

ArrayList<File> filesImage= new ArrayList<File>();
    ArrayList<File> filesBox= new ArrayList<File>();
 ArrayList<File[]> combinedFiles=new ArrayList<File[]>();
//add content to 2 lists here
File[] arrayFiles;

//add array image
arrayFiles = new File[filesImage.size()];
arrayFiles = filesImage.toArray(arrayFiles);
combinedFiles.add(arrayFiles);
//add array box
arrayFiles = new File[filesBox.size()];
arrayFiles = filesBox.toArray(arrayFiles);
combinedFiles.add(arrayFiles);

System.out.println(combinedFiles);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.