简体   繁体   中英

Most efficient way (according RAM/CPU consumption) to add elements from one ArrayList to another ArrayList to specific position

I have two ArrayLists A and B . I need to combine this two ArrayLists. Put all elements from ArrayList_ B to ArrayList_ A at specific places.

Element composition in the ArrayList_ A should looks like: a1b1a2b2a3b3....

But do this at the most efficiency way, as I can.

Rules : Do not change create ArrayList_ B .

As you can see, most efficient way in my example is Method2. But it's still very slow for huge ArrayList's.

Please, suggest the most efficient way how to do that. Thanks for your attention:).

public class Solution {

public static void main(String[] args) {

    Method1();
    Method2();
    Method3();

}

private static void Method3() {
    ArrayList<Object> a = new ArrayList<>();
    ArrayList<Object> b = new ArrayList<>();

    for (int i = 0; i < Math.pow(2, 15); i++) {
        a.add("a" + i);
    }
    for (int i = 0; i < Math.pow(2, 15); i++) {
        b.add("b" + i);
    }

    ArrayList<Object> aa = new ArrayList<>(a);
    a.ensureCapacity(2*aa.size());
    a.clear();

    long time1 = System.currentTimeMillis();


    for (int i = 0; i<b.size();i++) {
        a.add(aa.get(i));
        a.add(b.get(i));
    }
    long time2 = System.currentTimeMillis();

    System.out.println(time2 - time1);
}

private static void Method2() {
    ArrayList<Object> a = new ArrayList<>();
    ArrayList<Object> b = new ArrayList<>();

    for (int i = 0; i < Math.pow(2, 15); i++) {
        a.add("a" + i);
    }

    for (int i = 0; i < Math.pow(2, 15); i++) {
        b.add("b" + i);
    }

    long time1 = System.currentTimeMillis();

    int size = a.size();
    a.add(b.get(0));
    for (int i = 1; i < size; i++) {
        a.add(a.get(i));
        a.add(b.get(i));
    }
    a.subList(1, size).clear();

    long time2 = System.currentTimeMillis();

    System.out.println(time2 - time1);

}

private static void Method1() {
    ArrayList<Object> a = new ArrayList<>();
    ArrayList<Object> b = new ArrayList<>();

    for (int i = 0; i < Math.pow(2, 15); i++) {
        a.add("a" + i);
    }

    for (int i = 0; i < Math.pow(2, 15); i++) {
        b.add("b" + i);
    }

    long time1 = System.currentTimeMillis();

    a.add(1, b.get(0));
    for (int i = 1; i < b.size(); i++) {
        a.add((2 * i + 1), b.get(i));
    }

    long time2 = System.currentTimeMillis();

    System.out.println(time2 - time1);
}

}

Peter's answer is probably the best. However, if you are doing this a lot, perhaps define your own class. Skeleton code, perhaps buggy, assumes that your two input arrays a and b never change, you never want to change the combined list after creation , etc...:

public class DualList<E> extends AbstractList<E> {
   final List<E> a; 
   final List<E> b;

   public DualList(List<E> a, List<E> b) {
      this.a = a;  this.b = b;
   }

   public E get(int idx) {
      int half = idx >> 1;
      if ((idx & 1) == 1)
         return this.b.get(half);
      else
         return this.a.get(half);
   }

   // not sure what else you need or want to override...
}

This will obviously be way way quicker "creating" the combined list, since it does next to nothing, but this will be a little bit slower every time you call get() to retrieve an element. So final decision depends on just how may times you are calling get() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM