java - 如何遍历SparseArray?
有没有办法迭代Java SparseArray(适用于Android)? 我使用sparsearray轻松获取索引值。 我找不到一个。
Ruzanna asked 2019-02-04T11:44:50Z
9个解决方案
482 votes
似乎我找到了解决方案。 我没有正确注意到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);
}
Ruzanna answered 2019-02-04T11:45:04Z
167 votes
如果您不关心密钥,则可以使用valueAt(int)迭代稀疏数组以直接访问值。
for(int i = 0, nsize = sparseArray.size(); i < nsize; i++) {
Object obj = sparseArray.valueAt(i);
}
Pogo Lin answered 2019-02-04T11:45:26Z
16 votes
您只需创建自己的ListIterator:
public final class SparseArrayIterator implements ListIterator {
private final SparseArray 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 ListIterator iterate(SparseArray 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 ListIterator iterateAtKey(SparseArray 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 ListIterator iterateAt(SparseArray array, int location) {
return new SparseArrayIterator(array, location);
}
private SparseArrayIterator(SparseArray 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();
}
}
}
0101100101 answered 2019-02-04T11:45:48Z
9 votes
像饼一样简单。 只需确保在实际执行循环之前获取数组大小。
for(int i = 0, arraySize= mySparseArray.size(); i < arraySize; i++) {
Object obj = mySparseArray.get(/* int key = */ mySparseArray.keyAt(i));
}
希望这可以帮助。
Pascal answered 2019-02-04T11:46:11Z
7 votes
使用上面的循环导致从SparseArray删除所有元素到Exception。
要避免这种情况请按照以下代码使用普通循环从SparseArray中删除所有元素
private void getValues(){
for(int i=0; i
int key = sparseArray.keyAt(i);
Log.d("Element at "+key, " is "+sparseArray.get(key));
sparseArray.remove(key);
i=-1;
}
}
Sackurise answered 2019-02-04T11:46:39Z
6 votes
无论谁使用Kotlin,老实说,迭代SparseArray的最简单方法是:使用Anko或Android KTX的Kotlin扩展! (感谢Yazazzello指出Android KTX)
请致电forEach { i, item -> }
0101100101 answered 2019-02-04T11:47:08Z
4 votes
这里是SparseArray和Iterable> SparseArray的简单实现:
public class SparseArrayIterator implements Iterator {
private final SparseArray array;
private int index;
public SparseArrayIterator(SparseArray 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 implements Iterable {
private final SparseArray sparseArray;
public SparseArrayIterable(SparseArray sparseArray) {
this.sparseArray = sparseArray;
}
@Override
public Iterator iterator() {
return new SparseArrayIterator<>(sparseArray);
}
}
如果您不仅要迭代值而且要迭代密钥:
public class SparseKeyValue {
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 implements Iterator> {
private final SparseArray array;
private int index;
public SparseArrayKeyValueIterator(SparseArray array) {
this.array = array;
}
@Override
public boolean hasNext() {
return array.size() > index;
}
@Override
public SparseKeyValue next() {
SparseKeyValue keyValue = new SparseKeyValue<>(array.keyAt(index), array.valueAt(index));
index++;
return keyValue;
}
@Override
public void remove() {
array.removeAt(index);
}
}
public class SparseArrayKeyValueIterable implements Iterable> {
private final SparseArray sparseArray;
public SparseArrayKeyValueIterable(SparseArray sparseArray) {
this.sparseArray = sparseArray;
}
@Override
public Iterator> iterator() {
return new SparseArrayKeyValueIterator(sparseArray);
}
}
创建返回SparseArray和Iterable>的实用程序方法很有用:
public abstract class SparseArrayUtils {
public static Iterable> keyValueIterable(SparseArray sparseArray) {
return new SparseArrayKeyValueIterable<>(sparseArray);
}
public static Iterable iterable(SparseArray sparseArray) {
return new SparseArrayIterable<>(sparseArray);
}
}
现在你可以迭代SparseArray:
SparseArray a = ...;
for (String s: SparseArrayUtils.iterable(a)) {
// ...
}
for (SparseKeyValue s: SparseArrayUtils.keyValueIterable(a)) {
// ...
}
mixel answered 2019-02-04T11:47:49Z
-5 votes
答案是否定的,因为Map不提供它。 正如SparseArray所说,这个东西不提供任何接口。
您可以从Map循环并跳过返回SparseArray的值,但这是关于它的。
正如我在评论中所述,如果您需要迭代使用Map而不是SparseArray。例如,使用TreeMap按键顺序迭代。
TreeMap
John B answered 2019-02-04T11:48:24Z
-6 votes
接受的答案中有一些漏洞。 SparseArray的优点在于它允许空隙中的间隙。 所以,我们可以在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()检查这些indeces。 这是一个适配器的例子,我允许批量删除项目。
for (int index = 0; index < mAdapter.getItemCount(); index++) {
if (toDelete.get(index) == true) {
long idOfItemToDelete = (allItems.get(index).getId());
mDbManager.markItemForDeletion(idOfItemToDelete);
}
}
我认为理想情况下SparseArray系列会有一个getKeys()方法,但它没有。
Tyler Pfaff answered 2019-02-04T11:49:06Z