1

I have the following data in an ArrayList. Let's say it's a String ArrayList for convenience sake.

Mokey
MokeyBaby1
MokeyBaby2
MokeyBaby3
Dog
DogBaby1
DogBaby2
Cat
CatBaby1

I need to move the items that are related, together.

For example: Moving Monkey down. The new ArrayList would look like this.

Dog
DogBaby1
DogBaby2
Mokey
MokeyBaby1
MokeyBaby2
MokeyBaby3
Cat
CatBaby1

I already have a method that tells me which ArrayList indexes are related.

For example: getRelatedIndexes("Monkey") would return 0,1,2,3 for the original list.

I just need to know if there is an easy way to move all the items up or down an ArrayList together.

Thanks.

john
  • 1,561
  • 3
  • 20
  • 44

4 Answers4

1

You could wrap your list in a reorderable list and implement your reordering through that - at least you wouldn't need to hack the main list. It would maintain the order in an array of ints which you can then move around at will. You could even maintain the same data in several different orders if you like.

public static class OrderedList<T> extends AbstractList<T> {

    // The list I proxy.
    private final List<T> it;
    // The order.
    private final int[] order;

    public OrderedList(List<T> wrap) {
        it = wrap;
        order = new int[it.size()];
        // Initially the same order.
        for (int i = 0; i < order.length; i++) {
            order[i] = i;
        }
    }

    @Override
    public T get(int index) {
        return it.get(order[index]);
    }

    @Override
    public int size() {
        return it.size();
    }

    // TODO - Only moves up! Breaks on a down move.
    public void move(int start, int length, int to) {
        int[] move = new int[length];
        // Copy it out.
        System.arraycopy(order, start, move, 0, length);
        // Shift it down.
        System.arraycopy(order, start + length, order, start, to - start);
        // Pull it back in.
        System.arraycopy(move, 0, order, to, length);

    }
}

public void test() {
    List<String> t = Arrays.asList("Zero", "One", "Two", "Three", "Four", "Five");
    OrderedList<String> ordered = new OrderedList(t);
    System.out.println(ordered);
    ordered.move(1, 2, 3);
    System.out.println(ordered);
}

prints

[Zero, One, Two, Three, Four, Five]
[Zero, Three, Four, One, Two, Five]

Alternatively - use Collections.rotate and work out what sub-list should be rotated which way to achieve your move.

OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213
0

Perhaps this contains the solution you need (swap and/or rotate/sublist) - Moving items around in an ArrayList

Community
  • 1
  • 1
KarolDepka
  • 8,318
  • 10
  • 45
  • 58
  • Not really. This question is about moving just 1 item up and down. I want to move several. – john Dec 05 '14 at 14:05
  • Update: I'm looking into rotate now. I'll try it out and update this question. – john Dec 05 '14 at 14:06
0

The block shifting strategy can be achieved by

  • taking the elements out of the original list using List.remove(index) and adding into a new temporary array. Note this has to be done in reverse order otherwise the indexes will change as items are removed.
  • Adding the new temporary array into the desired location using List.addAll(index, collection)
  • list of indexes cloned in case it is being used elsewhere

Example

public static void main(String[] args) {
    List<Animal> animals = new ArrayList<Animal>(Arrays.asList(new Animal(
            "Mokey"), new Animal("MokeyBaby1"), new Animal("MokeyBaby2"),
            new Animal("MokeyBaby3"), new Animal("Dog"), new Animal(
                    "DogBaby1"), new Animal("DogBaby2"), new Animal("Cat"),
            new Animal("CatBaby1")));

    int[] relatedIndexes= { 0, 1, 2, 3 };
    shift(animals, relatedIndexes, 3);

    System.out.println(animals);
}

private static void shift(List<Animal> original, int[] indexes, int newIndex) {
    int[] sorted = indexes.clone();
    Arrays.sort(sorted);
    List<Animal> block = new ArrayList<Animal>();
    for (int i = sorted.length - 1; i >= 0; i--) {
        block.add(original.get(sorted[i]));
        original.remove(i);
    }
    original.addAll(newIndex, block);
}

Output

[Dog, DogBaby1, DogBaby2, Mokey, MokeyBaby1, MokeyBaby2, MokeyBaby3, Cat, CatBaby1]
Adam
  • 35,919
  • 9
  • 100
  • 137
  • Thanks for taking the time out for this. What I meant was, in the example I compared Strings and sorted in alphabetical order. This is not actual case. Actually I want to sort on a different condition, which is not alphabetical order (or related to strings at all), (this part is dealt with by the `getRelatedIndexes` method.). I hope I've made myself clear. – john Dec 05 '14 at 14:24
0

You could search for items in your list, which fullfill your criteria and safe them into another temporary list. Then you use the addAll(int index, Collection<? extends E> c) method to add these elements again to the list. Then you do not have to use add(int index, E element) for every Element itsself.

Jejeko
  • 1
  • 1