ArrayListを逆にする最も簡単な方法は何ですか?


333

このArrayListを逆にする最も簡単な方法は何ですか?

ArrayList<Integer> aList = new ArrayList<>();

//Add elements to ArrayList object
aList.add("1");
aList.add("2");
aList.add("3");
aList.add("4");
aList.add("5");

while (aList.listIterator().hasPrevious())
  Log.d("reverse", "" + aList.listIterator().previous());

回答:


798
Collections.reverse(aList);

例(リファレンス):

ArrayList aList = new ArrayList();
//Add elements to ArrayList object
aList.add("1");
aList.add("2");
aList.add("3");
aList.add("4");
aList.add("5");
Collections.reverse(aList);
System.out.println("After Reverse Order, ArrayList Contains : " + aList);

2
@AgarwalShankarエラーが発生しました。ArrayListでvoidが見つかりました。私は何かが足りないのですか。
Sagar Devanga 2015年

9
@SagarDevangaリストは元に戻され、返されません。
Carcigenicate

Collections.reverse(List); 私はそれをAndroidプロジェクトで使用しましたが、うまくいきます。
Damir Varevac

22

最も単純な方法ではありませんが、再帰が好きな場合は、ArrayListを逆にする次のメソッドに興味があるかもしれません。

public ArrayList<Object> reverse(ArrayList<Object> list) {
    if(list.size() > 1) {                   
        Object value = list.remove(0);
        reverse(list);
        list.add(value);
    }
    return list;
}

または非再帰的に:

public ArrayList<Object> reverse(ArrayList<Object> list) {
    for(int i = 0, j = list.size() - 1; i < j; i++) {
        list.add(i, list.remove(j));
    }
    return list;
}

私は間違っているかもしれませんが、非再帰的な例では、int j反復ごとに更新されませんか?あなたはそれを初期化しますが、繰り返しのたびに更新さj = list.size() - 1れる初期化セクションがそれを行うとは思いませんfor loopか?
Tony Chan

@Turbo jは、反復ごとに更新する必要はありません。これは、ArrayListの最後のインデックスに初期化され、最後の要素にアクセスするために使用されます。forループ内では、最後の要素が削除され、インデックスiに挿入されます。iは、ArrayListの最後から2番目の位置に到達するまで増加します。
トッド2014年

1
はい、しかし2回目の反復ではIndexOutOfBoundsException、アクセスしようとしているのでj(元のArrayListの最後のインデックス)、そのインデックスでオブジェクトを既に削除していませんか?
トニー・チャン、

1
申し訳ありませんが、コードを実行しただけで問題なく動作します。add()他の要素を配列に押し下げるのを忘れたので、配列は基本的に一定のサイズを維持します。興味深い解決策、ありがとう!
トニー・チャン

また、好奇心旺盛ですが、どのように再帰的な方法を思いついたのですか?それは私が普段考えていることではないと思います。
トニー・チャン

13

ここでの秘訣は、「逆」を定義することです。その場でリストを変更したり、逆の順序でコピーを作成したり、逆の順序でビューを作成したりできます。

最も簡単な方法は、直感的に言えばCollections.reverse次のとおりです。

Collections.reverse(myList);

このメソッドは、リストを適切に変更します。つまりCollections.reverse、リストを取得してその要素を上書きし、元に戻されないコピーを残しません。これは一部のユースケースには適していますが、他のユースケースには適していません。さらに、リストは変更可能であると想定しています。これが許容できる場合は、問題ありません。


そうでない場合は、逆の順序でコピーを作成できます

static <T> List<T> reverse(final List<T> list) {
    final List<T> result = new ArrayList<>(list);
    Collections.reverse(result);
    return result;
}

このアプローチは機能しますが、リストを2回繰り返す必要があります。コピーコンストラクター(new ArrayList<>(list))はリストを反復処理しCollections.reverseます。必要に応じて、このメソッドを書き換えて1回だけ繰り返すことができます。

static <T> List<T> reverse(final List<T> list) {
    final int size = list.size();
    final int last = size - 1;

    // create a new list, with exactly enough initial capacity to hold the (reversed) list
    final List<T> result = new ArrayList<>(size);

    // iterate through the list in reverse order and append to the result
    for (int i = last; i >= 0; --i) {
        final T element = list.get(i);
        result.add(element);
    }

    // result now holds a reversed copy of the original list
    return result;
}

これはより効率的ですが、より冗長です。

あるいは、Java 8のstreamAPI を使用するように上記を書き換えることもできます。これは、上記よりも簡潔で読みやすいと感じるもいます。

static <T> List<T> reverse(final List<T> list) {
    final int last = list.size() - 1;
    return IntStream.rangeClosed(0, last) // a stream of all valid indexes into the list
        .map(i -> (last - i))             // reverse order
        .mapToObj(list::get)              // map each index to a list element
        .collect(Collectors.toList());    // wrap them up in a list
}

nb。それは、Collectors.toList()結果のリストについては非常に少数の保証になります。結果がArrayListとして確実に返されるようにしたい場合は、Collectors.toCollection(ArrayList::new)代わりにを使用してください。


3番目のオプションは、逆の順序でビュー作成することです。これはより複雑な解決策であり、さらに読んだり、それ自体の質問に値するものです。GuavaのLists#reverseメソッドは、現実的な出発点です。

「最も単純な」実装を選択することは、読者の練習問題として残しておきます。


6

追加のArrayListまたはadd()メソッドとremove()メソッドの組み合わせを使用しないソリューション。巨大なリストを取り消す必要がある場合は、どちらも悪影響を与える可能性があります。

 public ArrayList<Object> reverse(ArrayList<Object> list) {

   for (int i = 0; i < list.size() / 2; i++) {
     Object temp = list.get(i);
     list.set(i, list.get(list.size() - i - 1));
     list.set(list.size() - i - 1, temp);
   }

   return list;
 }

5
ArrayList<Integer> myArray = new ArrayList<Integer>();

myArray.add(1);
myArray.add(2);
myArray.add(3);

int reverseArrayCounter = myArray.size() - 1;

for (int i = reverseArrayCounter; i >= 0; i--) {
    System.out.println(myArray.get(i));
}

2

要素を追加するための新しいリストを作成せずに、再帰的にArrayListを逆にします。

   public class ListUtil {

    public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<String>();
        arrayList.add("1");
        arrayList.add("2");
        arrayList.add("3");
        arrayList.add("4");
        arrayList.add("5");
        System.out.println("Reverse Order: " + reverse(arrayList));

    }

    public static <T> List<T> reverse(List<T> arrayList) {
        return reverse(arrayList,0,arrayList.size()-1);
    }
    public static <T> List<T> reverse(List<T> arrayList,int startIndex,int lastIndex) {

        if(startIndex<lastIndex) {
            T t=arrayList.get(lastIndex);
            arrayList.set(lastIndex,arrayList.get(startIndex));
            arrayList.set(startIndex,t);
            startIndex++;
            lastIndex--;
            reverse(arrayList,startIndex,lastIndex);
        }
        return arrayList;
    }

}

1

Java 8を使用している場合に備えて、Streamを利用できます。ArrayListはランダムアクセスリストであり、要素のストリームを逆の順序で取得し、それを新しいに収集できArrayListます。

public static void main(String[] args) {
        ArrayList<String> someDummyList = getDummyList();
        System.out.println(someDummyList);
        int size = someDummyList.size() - 1;
        ArrayList<String> someDummyListRev = IntStream.rangeClosed(0,size).mapToObj(i->someDummyList.get(size-i)).collect(Collectors.toCollection(ArrayList::new));
        System.out.println(someDummyListRev);
    }

    private static ArrayList<String> getDummyList() {
        ArrayList dummyList = new ArrayList();
        //Add elements to ArrayList object
        dummyList.add("A");
        dummyList.add("B");
        dummyList.add("C");
        dummyList.add("D");
        return dummyList;
    }

上記のアプローチは、ランダムアクセスではないため、LinkedListには適していません。instanceofチェックにも活用できます。


1

java 8を使用して同じことを行うこともできます。

public static<T> List<T> reverseList(List<T> list) {
        List<T> reverse = new ArrayList<>(list.size());

        list.stream()
                .collect(Collectors.toCollection(LinkedList::new))
                .descendingIterator()
                .forEachRemaining(reverse::add);

        return reverse;
    }

0

もう少し読みやすい:)

public static <T> ArrayList<T> reverse(ArrayList<T> list) {
    int length = list.size();
    ArrayList<T> result = new ArrayList<T>(length);

    for (int i = length - 1; i >= 0; i--) {
        result.add(list.get(i));
    }

    return result;
}

0

別の再帰的ソリューション

 public static String reverse(ArrayList<Float> list) {
   if (list.size() == 1) {
       return " " +list.get(0);
   }
   else {
       return " "+ list.remove(list.size() - 1) + reverse(list);
   } 
 }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.