Java SparseArray (Android 용)를 반복하는 방법이 있습니까? 나는 sparsearray
인덱스로 값을 쉽게 얻었습니다. 찾을 수 없습니다.
TreeMap<Integer, MyType>
키를 사용하여 순서대로 반복 할 수 있는 a 를 사용할 수 있습니다 . 언급했듯이 SparseArray는 HashMap보다 효율적으로 설계되었지만 반복을 허용하지 않습니다.
Java SparseArray (Android 용)를 반복하는 방법이 있습니까? 나는 sparsearray
인덱스로 값을 쉽게 얻었습니다. 찾을 수 없습니다.
TreeMap<Integer, MyType>
키를 사용하여 순서대로 반복 할 수 있는 a 를 사용할 수 있습니다 . 언급했듯이 SparseArray는 HashMap보다 효율적으로 설계되었지만 반복을 허용하지 않습니다.
답변:
해결책을 찾은 것 같습니다. 나는 그 keyAt(index)
기능을 제대로 알아 차리지 못했다 .
그래서 나는 다음과 같이 갈 것입니다 :
for(int i = 0; i < sparseArray.size(); i++) {
int key = sparseArray.keyAt(i);
// get the object by the key.
Object obj = sparseArray.get(key);
}
Object obj = sparseArray.valueAt(i);
valueAt(i)
보다 빠른입니다 get(key)
때문에, valueAt(i)
그리고 keyAt(i)
모두 O (1) , 그러나 get(key)
입니다 O (LOG2 N) 나는 확실히 항상 사용합니다, 그래서 valueAt
.
키를 신경 쓰지 않으면 valueAt(int)
스파 스 배열을 반복하면서 값을 직접 액세스하는 데 사용할 수 있습니다.
for(int i = 0, nsize = sparseArray.size(); i < nsize; i++) {
Object obj = sparseArray.valueAt(i);
}
sparseArray.size()
가 호출되지 않도록 하나 개의 변수에 size()
모든 시간을.
자신 만의 ListIterator를 작성해야합니다.
public final class SparseArrayIterator<E> implements ListIterator<E> {
private final SparseArray<E> array;
private int cursor;
private boolean cursorNowhere;
/**
* @param array
* to iterate over.
* @return A ListIterator on the elements of the SparseArray. The elements
* are iterated in the same order as they occur in the SparseArray.
* {@link #nextIndex()} and {@link #previousIndex()} return a
* SparseArray key, not an index! To get the index, call
* {@link android.util.SparseArray#indexOfKey(int)}.
*/
public static <E> ListIterator<E> iterate(SparseArray<E> array) {
return iterateAt(array, -1);
}
/**
* @param array
* to iterate over.
* @param key
* to start the iteration at. {@link android.util.SparseArray#indexOfKey(int)}
* < 0 results in the same call as {@link #iterate(android.util.SparseArray)}.
* @return A ListIterator on the elements of the SparseArray. The elements
* are iterated in the same order as they occur in the SparseArray.
* {@link #nextIndex()} and {@link #previousIndex()} return a
* SparseArray key, not an index! To get the index, call
* {@link android.util.SparseArray#indexOfKey(int)}.
*/
public static <E> ListIterator<E> iterateAtKey(SparseArray<E> array, int key) {
return iterateAt(array, array.indexOfKey(key));
}
/**
* @param array
* to iterate over.
* @param location
* to start the iteration at. Value < 0 results in the same call
* as {@link #iterate(android.util.SparseArray)}. Value >
* {@link android.util.SparseArray#size()} set to that size.
* @return A ListIterator on the elements of the SparseArray. The elements
* are iterated in the same order as they occur in the SparseArray.
* {@link #nextIndex()} and {@link #previousIndex()} return a
* SparseArray key, not an index! To get the index, call
* {@link android.util.SparseArray#indexOfKey(int)}.
*/
public static <E> ListIterator<E> iterateAt(SparseArray<E> array, int location) {
return new SparseArrayIterator<E>(array, location);
}
private SparseArrayIterator(SparseArray<E> array, int location) {
this.array = array;
if (location < 0) {
cursor = -1;
cursorNowhere = true;
} else if (location < array.size()) {
cursor = location;
cursorNowhere = false;
} else {
cursor = array.size() - 1;
cursorNowhere = true;
}
}
@Override
public boolean hasNext() {
return cursor < array.size() - 1;
}
@Override
public boolean hasPrevious() {
return cursorNowhere && cursor >= 0 || cursor > 0;
}
@Override
public int nextIndex() {
if (hasNext()) {
return array.keyAt(cursor + 1);
} else {
throw new NoSuchElementException();
}
}
@Override
public int previousIndex() {
if (hasPrevious()) {
if (cursorNowhere) {
return array.keyAt(cursor);
} else {
return array.keyAt(cursor - 1);
}
} else {
throw new NoSuchElementException();
}
}
@Override
public E next() {
if (hasNext()) {
if (cursorNowhere) {
cursorNowhere = false;
}
cursor++;
return array.valueAt(cursor);
} else {
throw new NoSuchElementException();
}
}
@Override
public E previous() {
if (hasPrevious()) {
if (cursorNowhere) {
cursorNowhere = false;
} else {
cursor--;
}
return array.valueAt(cursor);
} else {
throw new NoSuchElementException();
}
}
@Override
public void add(E object) {
throw new UnsupportedOperationException();
}
@Override
public void remove() {
if (!cursorNowhere) {
array.remove(array.keyAt(cursor));
cursorNowhere = true;
cursor--;
} else {
throw new IllegalStateException();
}
}
@Override
public void set(E object) {
if (!cursorNowhere) {
array.setValueAt(cursor, object);
} else {
throw new IllegalStateException();
}
}
}
Kotlin을 사용하는 사람이라면 SparseArray를 반복하는 가장 쉬운 방법은 다음과 같습니다. Anko 또는 Android KTX 의 Kotlin 확장 프로그램을 사용하십시오 ! (Android KTX를 지적하는 Yazazzello의 신용)
간단히 전화 forEach { i, item -> }
SparseArray
위의 루핑 을 사용하여 모든 요소를 제거하려면로 이어집니다 Exception
.
이를 피하려면 아래 코드를 따라 SparseArray
일반 루프 를 사용하여 모든 요소를 제거하십시오.
private void getValues(){
for(int i=0; i<sparseArray.size(); i++){
int key = sparseArray.keyAt(i);
Log.d("Element at "+key, " is "+sparseArray.get(key));
sparseArray.remove(key);
i=-1;
}
}
.clear()
선호되는 방법 이 있습니다.
i-=1;
현재 누락 된 요소를 설명 하기 위해 쓰려고한다고 가정 합니다. 그러나 루프를 되 돌리는 것이 좋습니다. for(int i=sparseArray.size()-1; i>=0; i++){...
; 또는while (sparseArray.size()>0) { int key=sparseArray.keyAt(0);...
다음은 간단 Iterator<T>
하고 Iterable<T>
구현 된 것입니다 SparseArray<T>
.
public class SparseArrayIterator<T> implements Iterator<T> {
private final SparseArray<T> array;
private int index;
public SparseArrayIterator(SparseArray<T> array) {
this.array = array;
}
@Override
public boolean hasNext() {
return array.size() > index;
}
@Override
public T next() {
return array.valueAt(index++);
}
@Override
public void remove() {
array.removeAt(index);
}
}
public class SparseArrayIterable<T> implements Iterable<T> {
private final SparseArray<T> sparseArray;
public SparseArrayIterable(SparseArray<T> sparseArray) {
this.sparseArray = sparseArray;
}
@Override
public Iterator<T> iterator() {
return new SparseArrayIterator<>(sparseArray);
}
}
값뿐만 아니라 키를 반복하려면 다음을 수행하십시오.
public class SparseKeyValue<T> {
private final int key;
private final T value;
public SparseKeyValue(int key, T value) {
this.key = key;
this.value = value;
}
public int getKey() {
return key;
}
public T getValue() {
return value;
}
}
public class SparseArrayKeyValueIterator<T> implements Iterator<SparseKeyValue<T>> {
private final SparseArray<T> array;
private int index;
public SparseArrayKeyValueIterator(SparseArray<T> array) {
this.array = array;
}
@Override
public boolean hasNext() {
return array.size() > index;
}
@Override
public SparseKeyValue<T> next() {
SparseKeyValue<T> keyValue = new SparseKeyValue<>(array.keyAt(index), array.valueAt(index));
index++;
return keyValue;
}
@Override
public void remove() {
array.removeAt(index);
}
}
public class SparseArrayKeyValueIterable<T> implements Iterable<SparseKeyValue<T>> {
private final SparseArray<T> sparseArray;
public SparseArrayKeyValueIterable(SparseArray<T> sparseArray) {
this.sparseArray = sparseArray;
}
@Override
public Iterator<SparseKeyValue<T>> iterator() {
return new SparseArrayKeyValueIterator<T>(sparseArray);
}
}
그것은 돌려주는 유틸리티 메소드를 작성하는 것이 유용 Iterable<T>
과 Iterable<SparseKeyValue<T>>
:
public abstract class SparseArrayUtils {
public static <T> Iterable<SparseKeyValue<T>> keyValueIterable(SparseArray<T> sparseArray) {
return new SparseArrayKeyValueIterable<>(sparseArray);
}
public static <T> Iterable<T> iterable(SparseArray<T> sparseArray) {
return new SparseArrayIterable<>(sparseArray);
}
}
이제 반복 할 수 있습니다 SparseArray<T>
:
SparseArray<String> a = ...;
for (String s: SparseArrayUtils.iterable(a)) {
// ...
}
for (SparseKeyValue<String> s: SparseArrayUtils.keyValueIterable(a)) {
// ...
}
Kotlin을 사용하는 경우 다음과 같은 확장 기능을 사용할 수 있습니다.
fun <T> LongSparseArray<T>.valuesIterator(): Iterator<T> {
val nSize = this.size()
return object : Iterator<T> {
var i = 0
override fun hasNext(): Boolean = i < nSize
override fun next(): T = valueAt(i++)
}
}
fun <T> LongSparseArray<T>.keysIterator(): Iterator<Long> {
val nSize = this.size()
return object : Iterator<Long> {
var i = 0
override fun hasNext(): Boolean = i < nSize
override fun next(): Long = keyAt(i++)
}
}
fun <T> LongSparseArray<T>.entriesIterator(): Iterator<Pair<Long, T>> {
val nSize = this.size()
return object : Iterator<Pair<Long, T>> {
var i = 0
override fun hasNext(): Boolean = i < nSize
override fun next() = Pair(keyAt(i), valueAt(i++))
}
}
원하는 경우 목록으로 변환 할 수도 있습니다. 예:
sparseArray.keysIterator().asSequence().toList()
나는 심지어 사용하여 삭제 항목에 안전 할 것 같아요 remove
(가)에 LongSparseArray
가 오름차순에서와 같이, (하지 반복자에) 그 자체.
편집 : collection-ktx ( 여기 예제 ) 를 사용하면 더 쉬운 방법이있는 것 같습니다 . 실제로 작성한 것과 매우 유사한 방식으로 구현되었습니다.
Gradle에는 다음이 필요합니다.
implementation 'androidx.core:core-ktx:#'
implementation 'androidx.collection:collection-ktx:#'
LongSparseArray 사용법은 다음과 같습니다.
val sparse= LongSparseArray<String>()
for (key in sparse.keyIterator()) {
}
for (value in sparse.valueIterator()) {
}
sparse.forEach { key, value ->
}
Java를 사용하는 사람들 은 예를 들어 LongSparseArrayKt.keyIterator
, LongSparseArrayKt.valueIterator
및을 사용할 수 있습니다 LongSparseArrayKt.forEach
. 다른 경우도 마찬가지입니다.
허용되는 답변에는 약간의 구멍이 있습니다. SparseArray의 장점은 indeces에 차이가 있다는 것입니다. 그래서 우리는 SparseArray에서 두 개의 맵을 가질 수 있습니다 ...
(0,true)
(250,true)
여기에서 크기는 2입니다. 크기를 반복하면 인덱스 0과 인덱스 1에 매핑 된 값의 값만 가져옵니다. 따라서 키 250의 매핑에는 액세스 할 수 없습니다.
for(int i = 0; i < sparseArray.size(); i++) {
int key = sparseArray.keyAt(i);
// get the object by the key.
Object obj = sparseArray.get(key);
}
이 작업을 수행하는 가장 좋은 방법은 데이터 세트의 크기를 반복 한 다음 배열의 get ()을 사용하여 해당 인덱스를 확인하는 것입니다. 다음은 항목의 일괄 삭제를 허용하는 어댑터의 예입니다.
for (int index = 0; index < mAdapter.getItemCount(); index++) {
if (toDelete.get(index) == true) {
long idOfItemToDelete = (allItems.get(index).getId());
mDbManager.markItemForDeletion(idOfItemToDelete);
}
}
이상적으로 SparseArray 제품군에는 getKeys () 메소드가 있지만 아쉽지 않습니다.
keyAt
방법은 n 번째 키의 값을 반환합니다 (이 예제 keyAt(1)
에서는 return 250
). 혼동하지 말고 get
키가 참조하는 요소의 값을 반환하십시오.