したがって、私のプログラムには、循環ArrayListのタイプが必要です。
それについての唯一の円形のものはget(int index)メソッドでなければなりません、これはオリジナルです:
/**
* Returns the element at the specified position in this list.
*
* @param index index of the element to return
* @return the element at the specified position in this list
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
インデックスが-1の場合、インデックスArrayList.size()-1の要素を取得する必要があり、インデックスがArrayList.size()の場合、インデックス0の要素を取得する必要があります。
これを実現する最も簡単な方法は、Java.utilパッケージからArrayListを拡張し、get(int index)をオーバーライドするだけなので、上記の2つのインデックスに対してIndexOutOfBoundsExceptionをスローせず、必要に応じて変更することです。範囲外の他のインデックスに対してIndexOutOfBoundsExceptionをスローします。
ただし、elementData(index)は
private transient Object[] elementData;
私のクラスはプライベートなので見られないので、私はそれを動作させることができません。
また、実際のcircularArrayは必要ないが、機能の一部のみであり、残りは次のものであるため、これに外部ライブラリを使用したくありません。通常のArrayList。
そこで、2つの質問があります。
どうすればこれを機能させることができますか? ArrayListクラス全体とAbstractCollection、Collection、およびIterableをプログラムにコピーせずに実行する方法はありますか?それは私にとっても悪いデザインのようです。
どうにかしてそれを機能させることができる場合、他に注意すべきことはありますか?上記の変更を行った場合、クラスの動作は希望どおりにしか変更されませんか、または他の望ましくない動作の変更がありますか?
編集:答えてくれてありがとう、私がやったことは次のとおりです:
import Java.util.ArrayList;
public class CircularArrayList<E> extends ArrayList<E>
{
private static final long serialVersionUID = 1L;
public E get(int index)
{
if (index == -1)
{
index = size()-1;
}
else if (index == size())
{
index = 0;
}
return super.get(index);
}
}
ArrayListをラップしますが、1つだけです。通常のArrayListインデックス以外の要素を使用して、最初と最後以外の要素にアクセスしようとすると、例外をスローします。
ArrayListから派生して、これらの行に沿ってget(int index)メソッドをオーバーライドすることはできません。
@Override
public E get(int index)
{
if(index < 0)
index = index + size();
return super.get(index);
}
私は何が欠けていますか?
この実装では、任意のインデックスを有効なインデックス範囲に折り畳むことはできませんが、左側と右側の両方からリストを適切にアドレス指定することができます(それぞれ正と負のインデックス、Pythonのように)。
get
フィールドにアクセスする必要なく、ArrayListクラスを拡張してelementData
メソッドの機能を変更できます。
_public class CircularList<E> extends ArrayList<E> {
@Override
public E get(int index) {
return super.get(index % size());
}
}
_
_super.get
_メソッドは引き続き範囲チェックを実行します(ただし、それらは失敗しません)。
これを行うと、ArrayListのインデックスが不安定になる可能性があることに注意してください。リストのサイズが変更されると、通常の範囲外のすべてのインデックスが変更されます。たとえば、リスト_['a','b','c','d','e']
_がある場合、get(7)
はc
を返します。 add('f')
を実行すると、b
は5を法としてではなく6を法として動作するため、get(7)
は突然get
を返します。
説明したのは、基本的に、必要なインデックスのモジュラスを取得し、リスト内のその要素にアクセスすることです。
継承を介した構成で次のことができます。
List<T>
のラッパークラスを作成し、ListWrapperを今すぐ呼び出します。wrapped
という名前を付けますなぜこのすべてのがらくたをするのですか?これは実装に依存しません。ある日、この便利さを別の実装で使用したいと思うかもしれません。その後、コードを複製する必要があり、地獄が始まります。 3番目の実装も必要な場合、ほんのわずかな新機能を追加するだけで、運命にあります。
間にラッパークラスがある場合:
覚えておいて、私たちは保守可能でなければならないプログラムを書いています!
ラッパークラス
public abstract class ListWrapper<T> implements List<T> {
protected final List<T> wrapped;
public ListWrapper(List<T> wrapped) {
this.wrapped = wrapped;
}
public T get(int index) {
return wrapped.get(index);
}
//omitting the other wrapper methods, for sake of brevity.
//Note: you still have to add them.
// Eclipse: Source menu, Generate Delegate methods does the trick nicely
}
実際の新しいクラス
public class ModList<T> extends ListWrapper<T> {
public ModList(List<T> list) {
super(list);
}
@Override
public T get(int index) {
int listSize = wrapped.size();
int indexToGet = index % listSize;
//this might happen to be negative
indexToGet = (indexToGet < 0) ? indexToGet+listSize : indexToGet;
return wrapped.get(indexToGet);
}
}
[〜#〜]注意[〜#〜]
選択された答えは、インデックスが非常に大きな負の数であり、リストのサイズが小さい場合、つまり、.
サイズ=> 10インデックス=> -1000000
以下は、すべてのサイズとインデックスを処理する実装です
import Java.util.ArrayList;
import Java.util.Collection;
/**
* A list the loops round to the first element when {@link CircularList#get(int)} is called with an
* index that is greater than the max index of the list and vice versa.
*
* @author Stuart Clark
*/
public class CircularList<E> extends ArrayList<E> {
public CircularList() {
super();
}
public CircularList(int initialCapacity) {
super(initialCapacity);
}
public CircularList(Collection<? extends E> c) {
super(c);
}
@Override
public E get(int index) {
if (isEmpty()) {
throw new IndexOutOfBoundsException("The list is empty");
}
while (index < 0) {
index = size() + index;
}
return super.get(index % size());
}
}
誰でもこのAbstractList拡張機能を知っていますか:com.Sun.appserv.management.util.misc.CircularList<T>
。それを見てください。 GlassFish Java.netコミュニティソリューションです。 GlassFish Container内のスレッドスケジューリングで使用されるため、強力なはずです。