回答:
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);
最も単純な方法ではありませんが、再帰が好きな場合は、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
か?
IndexOutOfBoundsException
、アクセスしようとしているのでj
(元のArrayListの最後のインデックス)、そのインデックスでオブジェクトを既に削除していませんか?
add()
他の要素を配列に押し下げるのを忘れたので、配列は基本的に一定のサイズを維持します。興味深い解決策、ありがとう!
ここでの秘訣は、「逆」を定義することです。その場でリストを変更したり、逆の順序でコピーを作成したり、逆の順序でビューを作成したりできます。
最も簡単な方法は、直感的に言えば、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のstream
API を使用するように上記を書き換えることもできます。これは、上記よりも簡潔で読みやすいと感じる人もいます。
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メソッドは、現実的な出発点です。
「最も単純な」実装を選択することは、読者の練習問題として残しておきます。
追加の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;
}
要素を追加するための新しいリストを作成せずに、再帰的に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;
}
}
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
チェックにも活用できます。
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;
}