My code compiles but doesn't work. I think i didn't typecast right? and can someone explain to me wrapIdx method return index % capacity. i don't really understand how that code wraps the array. when it reaches the end of the array index % capacity will return 1, but doesn't an array start at 0 index?
Here's my code, i'm implementing a Queue12 interface. After i get this to work, will i be able to make a test class to check if it works?
import java.util.NoSuchElementException;
public class QueueImpl12<T> implements Queue12<T>
{
private int _size, _backIdx, _frontIdx;
private static final int _defaultCapacity = 128;
private T[] _ringBuffer;
public QueueImpl12(int capacity)
{
_ringBuffer = (T[]) new Object[capacity];
clear();
}
public QueueImpl12()
{
_ringBuffer = (T[]) new Object[_defaultCapacity];
clear();
}
private int wrapIdx(int index)
{
return index % capacity();
}
public void clear()
{
_backIdx = 0;
_frontIdx = 0;
_size = 0;
}
#Override
public int capacity()
{
// TODO Auto-generated method stub
return _ringBuffer.length;
}
#Override
public int size()
{
// TODO Auto-generated method stub
return _size;
}
#Override
public boolean enqueue(T o)
{
//add o to back of queue
if(_ringBuffer.length == _size)
{
return false;
}
_ringBuffer[_backIdx] = o;
_backIdx = wrapIdx(_backIdx + 1 );
_size++;
return true;
}
#Override
public T dequeue()
{
if(_size == 0) //empty list
{
throw new NoSuchElementException();
}
T tempObj = _ringBuffer[_frontIdx]; //store frontIdx object
_ringBuffer[_frontIdx] = null;
_frontIdx++;
_size--;
return tempObj;
}
#Override
public T peek()
{
return _ringBuffer[_frontIdx];
}
}
So the first thing to note here is that the modulo operator % returns the remainder of a division. Any number modulo itself is 0, therefore when you hit the maximum capacity of the queue it will return 0, which is the index you will start at. If the code is returning 1 when it hits the end, you have an off by one issue.
Related
I have a class SimpleHistogram<DT> that takes in a generic array DT[] and I'm supposed to set the count, the number of times the element occurs in the array, of a specific item in the array to int count.
Here is what I have so far:
public class SimpleHistogram<DT> implements Histogram<DT>, Iterable<DT> {
DT[] items;
int size;
public SimpleHistogram() {
}
public SimpleHistogram(DT[] items) {
this.items = items;
}
#Override
public void setCount(DT item, int count) {
int n = 0;
Iterator<DT> L = this.iterator();
while (L.hasNext()) {
DT dt = L.next();
if (dt == item) { // if dt equals to item, meaning item IS present, then
n+=count; // set the count of the item to count
} else
{this.add(dt, count)} // if its not equal, meaning its not there, then add the item and the count of the item
}
}
private class Iterate implements Iterator<DT> {
int index = 0;
boolean lastRemoved = false;
#Override
public boolean hasNext() {
return (index < items.length-1);
}
#Override
public DT next() {
if (index < (items.length) -1)
throw new NoSuchElementException("No element at index");
DT object = items[index];
index++;
lastRemoved = false;
return object;
}
}
I'm struggling to implement the function setCount( DT item, int count) which is supposed to set the count of item to count.
Aditionally, if item does not exist already in the list, then we are supposed to add the item in and then set the count of the item to count.
I have provided explanations for what I intended to do but due to the fact that I am new to this, I haven't found sources that can properly clear this doubt, so any help would be greatly appreciated
Edit Here is the full code in case you may want to derive something from it. Test cases also presented below.
package histogram;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Iterator;
import java.util.NoSuchElementException;
// TODO: Uncomment this and make sure to implement all the methods
public class SimpleHistogram<DT> implements Histogram<DT>, Iterable<DT> {
DT[] items;
int size;
public SimpleHistogram() {
}
public SimpleHistogram(DT[] items) {
this.items = items;
}
#Override
public void setCount(DT item, int count) {
int n = 0;
Iterator<DT> L = this.iterator();
while (L.hasNext()) {
DT dt = L.next();
if (dt == item) { // if dt equals to item, meaning item IS present, then
n+=count; // set the count of the item to count
} else
{this.add(dt, count)} // if its not equal, meaning its not there, then add the item and the count of the item
}
}
private class Iterate implements Iterator<DT> {
int index = 0;
boolean lastRemoved = false;
#Override
public boolean hasNext() {
return (index < items.length-1);
}
#Override
public DT next() {
if (index < (items.length) -1)
throw new NoSuchElementException("No element at index");
DT object = items[index];
index++;
lastRemoved = false;
return object;
}
}
public int getCount(DT item) {
int n = 0;
Iterator<DT> L = this.iterator();
while (L.hasNext()) {
DT dt = L.next();
if (dt == item) {
n++;
}
}
return n;
}
#Override
public Iterator<DT> iterator() {
return new Iterate();
}
#Override
public int getTotalCount() {
return items.length;
}
}
Test cases:
public class SimpleHistogramTest {
#Test
public void testHistogram() {
Character[] target = {'a','b','c','a'};
Histogram<Character> h = new SimpleHistogram<>(target);
Iterator<Character> iter = h.iterator();
int elemCount = 0;
while(iter.hasNext()) {
iter.next();
elemCount++;
}
assertEquals(3, elemCount);
assertEquals(2, h.getCount('a'));
assertEquals(1, h.getCount('b'));
assertEquals(1, h.getCount('c'));
assertEquals(4, h.getTotalCount());
}
}
Would something like this satisfy the requirements? It's essentially a wrapper around a map, where the elements are the keys, and each value is a count of that element. Presumably, the Histogram interface has additional operations like getCount(T); here, you'd just get the count from the encapsulated map.
class SimpleHistogram<T> implements Histogram<T>, Iterable<T> {
private final Map<T, Integer> bins = new HashMap<>();
SimpleHistogram() {
this(List.of());
}
SimpleHistogram(List<? extends T> items) {
for (T item : items) {
Integer count = bins.getOrDefault(item, 0);
bins.put(item, count + 1);
}
}
#Override
public void setCount(T item, int count) {
bins.put(item, count);
}
#Override
public Iterator<T> iterator() {
return bins.keySet().iterator();
}
}
== compares the reference of an object in Java. equals() is also same.
If you want to compare two objects(dt and item) wit the same value, you need to override hashCode() and equals().
After that, you use equals() rather than ==.
Here is reference link.
Compare two objects with .equals() and == operator
I'm trying to implement a generic stack.
Here's the interface
package stack;
public interface Stack<T>{
void push(T number);
T pop();
T peek();
boolean isEmpty();
boolean isFull();
}
Here's the class
package stack;
import java.lang.reflect.Array;
import java.util.EmptyStackException;
public class StackArray <T> implements Stack<T>{
private int maxSize;
private T[] array;
private int top;
public StackArray(int maxSize) {
this.maxSize = maxSize;
// #SuppressWarnings("unchecked")
this.array = (T[]) Array.newInstance(StackArray.class, maxSize);
this.top = -1;
}
private T[] resizeArray() {
/**
* create a new array double the size of the old, copy the old elements then return the new array */
int newSize = maxSize * 2;
T[] newArray = (T[]) Array.newInstance(StackArray.class, newSize);
for(int i = 0; i < maxSize; i++) {
newArray[i] = this.array[i];
}
return newArray;
}
public boolean isEmpty() {
return top == -1;
}
public boolean isFull() {
return top == maxSize-1;
}
public void push(T element) {
if(!this.isFull()) {
++top;
array[top] = element;
}
else {
this.array = resizeArray();
array[++top] = element;
}
}
public T pop() {
if(!this.isEmpty())
return array[top--];
else {
throw new EmptyStackException();
}
}
public T peek() {
return array[top];
}
}
Here's the Main class
package stack;
public class Main {
public static void main(String[] args) {
String word = "Hello World!";
Stack <Character>stack = new StackArray<>(word.length());
// for(Character ch : word.toCharArray()) {
// stack.push(ch);
// }
for(int i = 0; i < word.length(); i++) {
stack.push(word.toCharArray()[i]);
}
String reversedWord = "";
while(!stack.isEmpty()) {
char ch = (char) stack.pop();
reversedWord += ch;
}
System.out.println(reversedWord);
}
}
The error is
Exception in thread "main" java.lang.ArrayStoreException: java.lang.Character
at stack.StackArray.push(StackArray.java:40)
at stack.Main.main(Main.java:14)
line 40 is in the push method
array[top] = element;
Side Question:
Any way to suppress the warning in the constructor? :)
The underlying issue is type erasure. The relevant implications of this means that an instance of the Stack class doesn't know it's type arguments at run-time. This is the reason why you can't just use the most natural solution here, array = new T[maxSize].
You've tried to work around this by creating an array using Array.newInstance(...), but unfortunately this array does not have elements of type T either. In the code shown the elements are of type StackArray, which is probably not what you intended.
One common way of dealing with this is to use an array of Object internally to Stack, and cast any return values to type T in accessor methods.
class StackArray<T> implements Stack<T> {
private int maxSize;
private Object[] array;
private int top;
public StackArray(int maxSize) {
this.maxSize = maxSize;
this.array = new Object[maxSize];
this.top = -1;
}
// ... lines removed ...
public T pop() {
if(this.isEmpty())
throw new EmptyStackException();
return element(top--);
}
public T peek() {
if(this.isEmpty())
throw new EmptyStackException();
return element(top);
}
// Safe because push(T) is type checked.
#SuppressWarnings("unchecked")
private T element(int index) {
return (T)array[index];
}
}
Note also you have a bug in the resizeArray() method where maxSize is never assigned a new value. You don't really need to keep track of maxSize, as you could just use array.length.
I think there is also an issue with peek() when the stack is empty in the original code.
Your code creates arrays of StackArray, and then you try to stick Character objects in it, just as if you were doing this:
static void add(Object arr[], Object o) {
arr[0] = o;
}
public static void main(String[] args) {
StackArray stack[] = new StackArray[1];
Character c = 'x';
add(stack, c);
}
So I've been tasked to create a method to remove an element from a MultiSet. I've been trying for a while, but sadly in vain. My code is as follows:
import java.util.*;
public class MultiSet<E> extends AbstractCollection<E> {
private HashMap<E, Integer> elements;
private int noOfElems;
public MultiSet() {
elements = new HashMap<E, Integer>();
noOfElems= 0;
}
public MultiSet(Collection<E> c) {
this();
addAll(c);
}
public int size() {
return noOfElems;
}
public Iterator<E> iterator() {
return new Iterator<E>() {
Iterator<E> iterator = elements.keySet().iterator();
int elemsLeft = 0;
E thisElem = null;
public boolean hasNext() {
return iterator.hasNext();
}
public E next() {
if (elemsLeft == 0) {
thisElem = iterator.next();
elemsLeft = elements.get(thisElem);
}
elemsLeft -= elemsLeft;
return null;
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
public boolean add(E e) {
Integer i = elements.get(e);
if(i == null) {
i = 1;
} else {
i += 1;
}
elements.put(e, i);
noOfElems++;
return true;
}
public String toString() {
return elements.toString();
}
public int hashCode() {
return elements.hashCode();
}
public boolean equals(MultiSet<E> other) {
if (this == other) {
return true;
}
if (other == null) {
return false;
}
if (this.getClass() != other.getClass()) {
return false;
}
MultiSet<?> obj = (MultiSet<?>) other;
return obj.elements.equals(elements);
}
public boolean remove(Object o) {
}
}
And I want to implement the remove method. Anything that will help me, even a few pointers on where to start, will be greatly appreciated. Thanks! (also, comments on the rest of my code will also be appreciated)
This multiset just stores the elements as hash keys mapped to a count of the number of occurrences. To remove all instances of an element, just delete the key:
public void remove_all(E e) {
elements.remove(e);
}
If you need to remove only one instance, then decrement the count unless it's already a 1. In that case, remove the key.
public void remove(E e) {
Integer i = elements.get(e);
if (i != null) {
if (i == 1) {
elements.remove(e);
} else {
elements.put(e, i - 1);
}
}
}
BTW it's a bit hard to believe this is your code. If you understand enough to write the methods you've already written, how could you not know even where to start on remove?
I have three classes, those being Lister, ObjectSortedList and SortedListProgram. I'm having trouble with the iterator for the generic class. What am I doing wrong?
This is the error I get:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 6
at objectsortedlist.ObjectSortedList.getData(ObjectSortedList.java:122)
at objectsortedlist.Lister.hasNext(Lister.java:28)
at objectsortedlist.SortedListProgram.main(SortedListProgram.java:52)
Java Result: 1
Here are my classes:
package objectsortedlist;
import java.util.Iterator;
/**
*
* #author Steven
*/
public class ObjectSortedList<T> implements Cloneable, Iterable<T> {
private T[] data;
private int capacity;
public ObjectSortedList()
{
final int init_capacity = 10;
capacity = 0;
data = (T[])new Object[init_capacity];
}
public ObjectSortedList(int init_capacity)
{
if(init_capacity < 0)
throw new IllegalArgumentException("Initial capacity is negative: " + init_capacity);
capacity = 0;
data = (T[])new Object[init_capacity];
}
private boolean empty()
{
if(data.length == 0 || data[0] == null)
return true;
else
return false;
}
public int length()
{
return capacity;
}
public void insert(T element)
{
if(capacity == data.length)
{
ensureCapacity(capacity * 2 + 1);
}
data[capacity] = element;
capacity++;
}
public boolean delete(T target)
{
int index;
if(target == null)
{
index = 0;
while((index < capacity) && (data[index] != null))
index++;
}
else
{
index = 0;
while((index < capacity) && (!target.equals(data[index])))
index++;
}
if(index == capacity)
return false;
else
{
capacity--;
data[index] = data[capacity];
data[capacity] = null;
return true;
}
}
private void ensureCapacity(int minCapacity)
{
T[] placeholder;
if(data.length < minCapacity)
{
placeholder = (T[])new Object[minCapacity];
System.arraycopy(data, 0, placeholder, 0, capacity);
data = placeholder;
}
}
public ObjectSortedList<T> clone()
{
// Cloning
ObjectSortedList<T> answer;
try
{
answer = (ObjectSortedList<T>) super.clone();
}
catch(CloneNotSupportedException cnse)
{
throw new RuntimeException("This class does not implement cloneable.");
}
answer.data = data.clone();
return answer;
}
#Override
public Iterator<T> iterator()
{
return (Iterator<T>) new Lister<T>(this, 0);
}
public T getData(int index)
{
return (T)data[index];
}
}
package objectsortedlist;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
*
* #author Steven
*/
public class Lister<T> implements Iterator<T>
{
private ObjectSortedList<T> current;
private int index;
public Lister(ObjectSortedList<T> top, int index)
{
current = top;
this.index = index;
}
#Override
public boolean hasNext()
{
return (current.getData(index) == null);
}
#Override
public T next()
{
T answer;
if(!hasNext())
throw new NoSuchElementException("The Lister is empty.");
answer = current.getData(index+1);
return answer;
}
#Override
public void remove() {
throw new UnsupportedOperationException("Don't use this. Use objectsortedlist.SortedList.delete(T target).");
}
}
package objectsortedlist;
import java.util.Scanner;
/**
*
* #author Steven
*/
public class SortedListProgram {
private static Scanner scan = new Scanner(System.in);
private static String[] phraseArray = {"Hullabaloo!", "Jiggery pokery!", "Fantastic!", "Brilliant!", "Clever!", "Geronimo!", "Fish sticks and custard.", "Spoilers!",
"Exterminate!", "Delete!", "Wibbly-wobbly!", "Timey-wimey!"};
private static Lister<String> print;
public static void main(String args[])
{
int phraseNo = 0;
System.out.println("I'm gonna say some things at you, and you're going to like it."
+ " How many things would you like me to say to you? Put in an integer from 1-12, please.");
try
{
phraseNo = Integer.parseInt(scan.nextLine());
while((phraseNo < 1) || (phraseNo > 12))
{
System.out.println("The integer you entered wasn't between 1 and 12. Make it in between those numbers. Please? Pleaseeeee?");
phraseNo = Integer.parseInt(scan.nextLine());
}
}
catch(NumberFormatException nfe)
{
System.out.println("C'mon, why don't you follow directions?");
phraseNo = 0;
}
if(phraseNo == 0);
else
{
ObjectSortedList<String> phrases = new ObjectSortedList<String>(phraseNo);
for(int i = 0; i < phrases.length(); i++)
{
phrases.insert(phraseArray[i]);
}
print = new Lister<String>(phrases, phraseNo);
while(print.hasNext())
System.out.println(print.next());
}
}
}
After looking at your code I found multiple issues, here are they:
In your SortedListProgram class, in following code the phrases.length() will be 0, so the it will never go in that loop.
ObjectSortedList<String> phrases = new ObjectSortedList<String>(phraseNo);
for(int i = 0; i < phrases.length(); i++)
{
phrases.insert(phraseArray[i]);
}
Moreover in SortedListProgram class's this call sequence
print.hasNext() -> current.getData(index)
the index passed is equal to size of data array field in the
ObjectSortedList class and Since in java array indexes ranges from
zero to array size -1. So you are bound to get
java.lang.ArrayIndexOutOfBoundsException always.
Please correct your code.
Is there a way to iterate over Java SparseArray (for Android) ? I used sparsearray to easily get values by index. I could not find one.
Seems I found the solution. I hadn't properly noticed the keyAt(index) function.
So I'll go with something like this:
for(int i = 0; i < sparseArray.size(); i++) {
int key = sparseArray.keyAt(i);
// get the object by the key.
Object obj = sparseArray.get(key);
}
If you don't care about the keys, then valueAt(int) can be used to while iterating through the sparse array to access the values directly.
for(int i = 0, nsize = sparseArray.size(); i < nsize; i++) {
Object obj = sparseArray.valueAt(i);
}
Ooor you just create your own 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();
}
}
}
For whoever is using Kotlin, honestly the by far easiest way to iterate over a SparseArray is: Use the Kotlin extension from Anko or Android KTX! (credit to Yazazzello for pointing out Android KTX)
Simply call forEach { i, item -> }
Simple as Pie. Just make sure you fetch array size before actually performing the loop.
for(int i = 0, arraySize= mySparseArray.size(); i < arraySize; i++) {
Object obj = mySparseArray.get(/* int key = */ mySparseArray.keyAt(i));
}
Hope this helps.
For removing all the elements from SparseArray using the above looping leads to Exception.
To avoid this Follow the below code to remove all the elements from SparseArray using normal loops
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;
}
}
Here is simple Iterator<T> and Iterable<T> implementations for 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);
}
}
If you want to iterate not only a value but also a key:
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);
}
}
It's useful to create utility methods that return Iterable<T> and 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);
}
}
Now you can iterate SparseArray<T>:
SparseArray<String> a = ...;
for (String s: SparseArrayUtils.iterable(a)) {
// ...
}
for (SparseKeyValue<String> s: SparseArrayUtils.keyValueIterable(a)) {
// ...
}
If you use Kotlin, you can use extension functions as such, for example:
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++))
}
}
You can also convert to a list, if you wish. Example:
sparseArray.keysIterator().asSequence().toList()
I think it might even be safe to delete items using remove on the LongSparseArray itself (not on the iterator), as it is in ascending order.
EDIT: Seems there is even an easier way, by using collection-ktx (example here) . It's implemented in a very similar way to what I wrote, actally.
Gradle requires this:
implementation 'androidx.core:core-ktx:#'
implementation 'androidx.collection:collection-ktx:#'
Here's the usage for LongSparseArray :
val sparse= LongSparseArray<String>()
for (key in sparse.keyIterator()) {
}
for (value in sparse.valueIterator()) {
}
sparse.forEach { key, value ->
}
And for those that use Java, you can use LongSparseArrayKt.keyIterator , LongSparseArrayKt.valueIterator and LongSparseArrayKt.forEach , for example. Same for the other cases.
The answer is no because SparseArray doesn't provide it. As pst put it, this thing doesn't provide any interfaces.
You could loop from 0 - size() and skip values that return null, but that is about it.
As I state in my comment, if you need to iterate use a Map instead of a SparseArray. For example, use a TreeMap which iterates in order by the key.
TreeMap<Integer, MyType>
The accepted answer has some holes in it. The beauty of the SparseArray is that it allows gaps in the indeces. So, we could have two maps like so, in a SparseArray...
(0,true)
(250,true)
Notice the size here would be 2. If we iterate over size, we will only get values for the values mapped to index 0 and index 1. So the mapping with a key of 250 is not accessed.
for(int i = 0; i < sparseArray.size(); i++) {
int key = sparseArray.keyAt(i);
// get the object by the key.
Object obj = sparseArray.get(key);
}
The best way to do this is to iterate over the size of your data set, then check those indeces with a get() on the array. Here is an example with an adapter where I am allowing batch delete of items.
for (int index = 0; index < mAdapter.getItemCount(); index++) {
if (toDelete.get(index) == true) {
long idOfItemToDelete = (allItems.get(index).getId());
mDbManager.markItemForDeletion(idOfItemToDelete);
}
}
I think ideally the SparseArray family would have a getKeys() method, but alas it does not.