john
john

Reputation: 1747

Moving several items in an ArrayList

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.

Upvotes: 1

Views: 533

Answers (4)

OldCurmudgeon
OldCurmudgeon

Reputation: 65811

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.

Upvotes: 1

Adam
Adam

Reputation: 36703

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]

Upvotes: 0

Jejeko
Jejeko

Reputation: 1

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.

Upvotes: 0

KarolDepka
KarolDepka

Reputation: 8628

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

Upvotes: 0

Related Questions