I have the following code ArrayList implementation
public class LongArrayListUnsafe {
public static void main(String[] args) {
LongArrayList dal1 = LongArrayList.withElements();
for (int i = 0; i < 1000; i++)
dal1.add(i);
// Runtime.getRuntime().availableProcessors()
ExecutorService executorService = Executors.newFixedThreadPool(4);
long start = System.nanoTime();
for (int i = 0; i < 100; i++) {
executorService.execute(new Runnable() {
public void run() {
for (int i = 0; i < 1000; i++)
dal1.size();
for (int i = 0; i < 1000; i++)
dal1.get(i % 100);
}
});
}
executorService.shutdown();
try {
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
System.out.println("mayor disaster!");
}
}
class LongArrayList {
private long[] items;
private int size;
public LongArrayList() {
reset();
}
public static LongArrayList withElements(long...initialValues) {
LongArrayList list = new LongArrayList();
for (long l: initialValues)
list.add(l);
return list;
}
// Number of items in the double list
public synchronized int size() {
return size;
}
// Return item number i
public synchronized long get(int i) {
if (0 <= i && i < size)
return items[i];
else
throw new IndexOutOfBoundsException(String.valueOf(i));
}
// Add item x to end of list
public synchronized LongArrayList add(long x) {
if (size == items.length) {
long[] newItems = new long[items.length * 2];
for (int i = 0; i < items.length; i++)
newItems[i] = items[i];
items = newItems;
}
items[size] = x;
size++;
return this;
}
Now, this concurrent drivercode simply reads of the list, which is already made.This goes pretty fast.
But I was wondering whether it would be possible
for me to do this onlyreading operation faster with a readwritelock.
In size and get, this looks like this:
synchronized public int size() {
readWriteLock.readLock().lock();
int ret = this.size.get();
readWriteLock.readLock().unlock();
return ret;
}
and
public long get(int i) {
readWriteLock.readLock().lock();
if (0 <= i && i < size.get()) {
long ret = items.get(i);
readWriteLock.readLock().unlock();
return ret;
} else {
throw new IndexOutOfBoundsException(String.valueOf(i));
}
}
However, using a readwritelock goes way slower, and even slower when I add more threads. Why is this? when my drivercode is only reading, the threads should have more or less unlimited acces to the methods?
A java.util.concurrent.locks.ReadWriteLock is an inherently more complex thing than a mutual exclusion lock like synchronized. The documentation of the class states this. The overhead of the read-write semantics are likely bigger than return this.size;, or return this.items[i];, even with a surrounding boundary check.
Let's also look at your proposal in particular. You want to replace the original
public synchronized int size() {
return size;
}
with the proposal
synchronized public int size() { // <-- locks exclusively/mutually on "this"
readWriteLock.readLock().lock(); // <-- locks on readWriteLock.readLock()
int ret = this.size.get(); // <-- is size and AtomicInteger now?
readWriteLock.readLock().unlock();
return ret;
}
I assume the use of synchronized was a typo, or it would add another lock to the equation. Also, I assume this.size.get(); should be this.size;. (using an AttomicInteger for size makes no sense in this context and adds additional cost). If my assumptions are correct, your actual proposal would be:
public int size() {
readWriteLock.readLock().lock();
int ret = this.size;
readWriteLock.readLock().unlock();
return ret;
}
public long get(int i) {
readWriteLock.readLock().lock();
if (0 <= i && i < this.size) {
long ret = items[i];
readWriteLock.readLock().unlock();
return ret;
} else {
throw new IndexOutOfBoundsException(String.valueOf(i));
}
}
public LongArrayList add(long x) {
readWriteLock.writeLock().lock();
if (size == items.length) {
long[] newItems = new long[items.length * 2];
for (int i = 0; i < items.length; i++)
newItems[i] = items[i];
this.items = newItems;
}
items[size] = x;
size++;
readWriteLock.writeLock().unlock();
return this;
}
The implementation of get(int) is dangerous. If an IndexOutOfBoundException is thrown, the read-lock remains locked forever. That won't slow down further reads, but it keeps all future calls to add(long) waiting. If you use a lock, it is advisable to use it in combination with finally to ensure it is unlocked:
public long get(int i) {
readWriteLock.readLock().lock();
try {
if (0 <= i && i < size) {
return items[i];
}
throw new IndexOutOfBoundsException(String.valueOf(i));
}
finally {
readWriteLock.readLock().unlock();
}
}
public LongArrayList add(long x) {
readWriteLock.writeLock().lock();
try {
if (size == items.length) {
long[] newItems = new long[items.length * 2];
for (int i = 0; i < items.length; i++)
newItems[i] = items[i];
items = newItems;
}
items[size] = x;
size++;
}
finally {
readWriteLock.writeLock().unlock();
}
return this;
}
As mentioned, if you are reading far more than you write, using synchronized could be more performant.
Related
Basically it's a array list implementation and I need to time how long it takes to add elements to it, along with other features. I compiled it though and there's no output and I can't find the problem. I instantiate an array of objects in the class then defined a method add(E e) to add an element E using basic assignment. Then the ListDriver should populate the array using the add() method and print it, but again, no output.
public class MyArrayList<E> {
public Object array[];
public int size = 0;
private static final int INITIAL_CAPACITY = 100;
public MyArrayList() {
array = new Object[INITIAL_CAPACITY];
this.size = 0;
}
private boolean arrayFull() {
if (size == array.length)
return true;
else
return false;
}
private boolean remove(Object o) {
for (int i = 0; i < size; i++) {
if (array[i].getClass() == o.getClass()) {
remove(i);
return true;
}
}
return false;
}
private void resize(int i) {
if (i == 0) {
Object[] temp = new Object[array.length*2];
for (int j = 0; j < size; j++) {
temp[j] = array[j];
}
this.array = temp;
}
if (i == 1) {
Object[] temp = new Object[array.length/2];
for (int j = 0; j < size; j++) {
temp[j] = array[j];
}
this.array = temp;
}
}
public void add(E e) {
if (!arrayFull()) {
array[size] = e;
size++;
}
else if (arrayFull()) {
resize(0);
add(e);
}
}
public int size() {
return size;
}
private void clear() {
array = null;
}
private Object remove(int index) {
if (halfFull()) {
resize(1);
}
Object temp = array[index];
for (int i = index; i < size; i++) {
array[i] = array[i+1];
}
size--;
return temp;
}
private boolean halfFull() {
if (size < (array.length/4)) {
return true;
}
else return false;
}
public void add(int index, E element) {
if (!arrayFull()) {
for (int i = size-1 ; i >= index ; i--) {
array[i] = array[i+1];
}
array[index] = element;
size++;
}
else {
resize(0);
add(index, element);
}
}
public String toString() {
String list = new String();
for (int i = 0; i < size; i++) {
list += " " + array[i];
}
return list;
}
public static void main(String[] args) {
MyArrayList temp = new MyArrayList();
System.out.println(temp.size);
}
}
And the driver
public class ListTester {
public static void main(String[] args) {
int n = 100;
MyArrayList arrayList = new MyArrayList();
int[] array = new int[n];
for (int i = 0; i < array.length; i++) {
array[i] = (int)Math.random() *2*n +1;
}
long startTime = System.nanoTime();
for (int i = 0; i < arrayList.size(); i++) {
arrayList.add(array[i]);
}
long endTime = System.nanoTime();
long duration = endTime - startTime;
System.out.println(arrayList);
System.out.println(duration);
}
}
import java.util.Arrays;
import java.util.Iterator;
public class ArrayList<Type> implements Iterable<Type> {
Type[] arr = (Type[]) new Object[10];
int size = 0;
//change capacity
public void newCapacity(int i) {
if (i == 0) {
int newIncreasedCapacity = arr.length * 2;
arr = Arrays.copyOf(arr, newIncreasedCapacity);
} else if (i == 1) {
int newDecreasedCapacity = arr.length / 2;
arr = Arrays.copyOf(arr, newDecreasedCapacity);
}
}
// add an item
public void add(Type item) {
if (size == arr.length) {
newCapacity(0);
}
arr[size++] = item; //increases size after appending
}
//remove an item
public Type remove(int index) {
if (size <= arr.length / 4) {
newCapacity(1);
}
Type removedItem = (Type) arr[index];
for (int i = index; i < size - 1; i++) {
arr[i] = arr[i + 1];
}
size -= 1;
return removedItem;
}
public int size() {
int count = 0;
for (int i = 0; i < size; i++) {
count += 1;
}
return count;
}
#Override
public Iterator<Type> iterator() {
return new ArrayIterator(arr);
}
class ArrayIterator<Type> implements Iterator<Type> {
private Type[] arrayList;
public ArrayIterator(Type[] newArray) {
arrayList = newArray;
}
// check if next element not null
public boolean hasNext() {
return (arrayList[size + 1] != null);
}
// next element
public Type next() {
if (arrayList[size + 1] != null) {
return (arrayList[size + 1]);
} else {
return null;
}
}
}
// Main Method
public static void main(String[] args) {
ArrayList<Integer> new_arr = new ArrayList<>();
new_arr.add(5);
new_arr.add(7);
new_arr.add(9);
new_arr.remove(0);
System.out.println(new_arr.size());
for (int i : new_arr) {
System.out.println(new_arr.size());
System.out.println(i);
}
}
}
I implemented the code for a custom ArrayList and also implemented an iterator for my custom data type, but I am facing an issue.
So when i run the for each loop in the main method, the loop does not run and thus nothing is printed on the console.I have checked the array which is being used for the for-each loop is not empty.Please help!
I think that you should fix your Iterator to something like
class ArrayIterator<Type> implements Iterator<Type> {
private Type[] arrayList;
private int position;
public ArrayIterator(Type[] newArray) {
arrayList = newArray;
position = 0;
}
// check if next element not null
public boolean hasNext() {
return (position != size);
}
// next element
public Type next() {
if (arrayList[position] != null) {
return (arrayList[position++]);
} else {
return null;
}
}
}
You are using the position of the size of the array to calculate the next() and hasNext(), the hasNext() is always returning null.
I'm new to Java and I'm having some problems shuffling a list.
I have to write the Iterable class so that when you iterate over the queue it returns the items in a randomly order. That's why I wrote that shuffle method and then I'm calling it inside RandomizedQueueIterator class
import java.util.Iterator;
import java.util.NoSuchElementException;
public class RandomizedQueue<Item> implements Iterable<Item>
{
// instance variables
private Item[] queue;
private int N = 0;
private int R = 0;
// constructor
public RandomizedQueue()
{
queue = (Item[]) new Object[1];
}
// helper functions
private void resize(int capacity)
{
Item[] copy = (Item[]) new Object[capacity];
for (int i = 0; i < N; i++)
copy[i] = queue[i];
queue = copy;
}
private void shrink(int capacity)
{
Item[] copy = (Item[]) new Object[capacity];
int M = 0;
for (int i = 0; i < N; i++)
{
if (queue[i] != null)
copy[M++] = queue[i];
}
queue = copy;
}
// shuffle queue
private void shuffle(Item[] a )
{
int N = a.length;
for (int i = 0; i < N; i++)
{
int r = StdRandom.uniform(i + 1);
Item temp = a[r];
a[r] = a[i];
a[i] = temp;
}
}
// return wether queue is empty
public boolean isEmpty() { return queue.length == 0; }
// return size of queue
public int size() { return queue.length; }
// add item to the queue
public void enqueue(Item item)
{
if (N == queue.length) { resize(N*2); }
queue[N++] = item;
}
// remove and return a random item from the queue
public Item deque()
{
// generate a random index and store item
int random_index;
do {
random_index = StdRandom.uniform(0, N);
} while (queue[random_index] == null);
Item item = queue[random_index];
// delete item from array and increment counter of null items
queue[random_index] = null;
R += 1;
// shrink array if corresponds
if (R == (3/4 * N)) { shrink(N/2); }
// return item
return item;
}
// return a random item from the queue
public Item sample()
{
// generate a random index and store item
int random_index;
do {
random_index = StdRandom.uniform(0, N);
} while (queue[random_index] == null);
Item item = queue[random_index];
// return item
return item;
}
// iteration
public Iterator<Item> iterator()
{
return new RandomizedQueueIterator();
}
private class RandomizedQueueIterator implements Iterator<Item>
{
private int i = 0;
shuffle(queue);
public boolean hasNext()
{
return i < N;
}
public Item next()
{
if (i >= N)
{
throw java.util.NoSuchElementException;
}
return queue[i++];
}
public void remove()
{
throw new UnsupportedOperationException("Invalid operation for array");
}
}
// main method
public static void main(String[] args)
{
RandomizedQueue example = new RandomizedQueue();
example.enqueue(0);
example.enqueue(1);
example.enqueue(2);
example.enqueue(3);
example.enqueue(3);
example.enqueue(3);
example.enqueue(3);
}
}
The output when trying to compile:
2 errors found:
[line: 114] Error: invalid method declaration; return type required
[line: 114] Error: expected
line:114 > shuffle(queue);
Any help would be really appreciated.
Thanks
If you want to run the class you need to put the method call in a main method
public static void main(String...args) {
shuffle(list_test);
}
If you do this you will either define list_test as a static variable or define it inside the main method.
There are a couple of problems. One of the problems is that you are calling the function method "inside" your class not in a function. You should be calling the function outside after you have create the test object.
So In your main. Call:
list_test = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
test testObj = new test();
newList = test.shuffle(list_test); // in the case it returns a new list
where
private void shuffle(int[] a )
// and returns a new list
return shuffled_list
If you only care about shuffling items in your list, use the JDK built-in shuffle() method instead.
There are quite a few things that can be improved. Your class might look like this:
import java.util.Arrays;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Random;
// it is standard to use E or T for collections
public class RandomizedQueue<E> implements Iterable<E> {
// most java collections have a default size of 16, set at 2 for testing
private static final int DEFAULT_INITIAL_CAPACITY = 2;
private static final Random GENERATOR = new Random();
// have good variable names
private boolean iterating = false; // to avoid concurrent modification
private E[] queue;
private int size = 0;
#SuppressWarnings("unchecked")
public RandomizedQueue() {
queue = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
}
// remove and return a random item from the queue
public E dequeue() {
if (iterating) {
throw new ConcurrentModificationException();
}
return dequeue(GENERATOR.nextInt(size));
}
// add item to queue
public void enqueue(E item) {
if (iterating) {
throw new ConcurrentModificationException();
}
if (size == queue.length) {
resize(size * 2);
}
queue[size++] = item;
}
// return whether queue is empty
public boolean isEmpty() {
return size == 0;
}
// iteration
public Iterator<E> iterator() {
return new RandomizedQueueIterator();
}
// return a random item from the queue
public E sample() {
if (isEmpty()) {
throw new NoSuchElementException("trying to sample from empty queue");
}
return queue[GENERATOR.nextInt(size)];
}
// shuffle queue
public void shuffle() {
for (int i = size - 1; i >= 0; i--) {
swap(i, GENERATOR.nextInt(i + 1));
}
}
// return size of queue
public int size() {
return size;
}
// helper functions
private E dequeue(int randomIndex) {
if (isEmpty()) {
throw new NoSuchElementException("trying to remove from empty queue");
}
size--;
// resize if only 1/4 of the queue is full
if (size < queue.length / 4) {
resize(queue.length / 2);
}
// since all get data methods are random, only need to swap on remove
swap(randomIndex, size);
E randomItem = queue[size];
queue[size] = null;
return randomItem;
}
private void resize(int capacity) {
// copyOf is substantially faster since it uses arraycopy which is in native code
queue = Arrays.copyOf(queue, capacity);
}
// swap data at indices i and j
private void swap(int i, int j) {
E temp = queue[j];
queue[j] = queue[i];
queue[i] = temp;
}
private class RandomizedQueueIterator implements Iterator<E> {
private int currentIndex = 0;
private int indexToRemove = -1;
private RandomizedQueueIterator() {
iterating = true;
shuffle();
}
public boolean hasNext() {
return currentIndex < size;
}
public E next() {
if (currentIndex >= size) {
throw new NoSuchElementException();
}
indexToRemove = currentIndex;
E nextElement = queue[currentIndex++];
if (currentIndex == size) {
iterating = false;
}
return nextElement;
}
public void remove() {
if (indexToRemove == -1) {
throw new IllegalStateException();
}
// print for testing
System.out.println("r: " + dequeue(indexToRemove));
currentIndex--;
indexToRemove = -1;
}
}
// main method
public static void main(String[] args) {
int exampleSize = 7;
System.out.println("example 1:");
RandomizedQueue<Integer> example1 = new RandomizedQueue<>();
for (int i = 0; i < exampleSize; i++) {
example1.enqueue(i);
}
System.out.println("size: " + example1.size());
for (int i = 0; i < exampleSize; i++) {
System.out.println("d: " + example1.dequeue());
}
System.out.println("size: " + example1.size());
System.out.println("\nexample 2:");
RandomizedQueue<Integer> example2 = new RandomizedQueue<>();
for (int i = 0; i < exampleSize; i++) {
example2.enqueue(i);
}
System.out.println("size: " + example2.size());
Iterator<Integer> iterator = example2.iterator();
// iterator.remove(); throws IllegalStateException
while (iterator.hasNext()) {
System.out.println("i: " + iterator.next());
iterator.remove();
System.out.println("size: " + example2.size());
// iterator.remove(); should throws IllegalStateException
}
}
}
Use this to give you ideas on how to write your class.
I have written my own priority_queue based on unsorted array, so adding new element works fast in O(1) but removing element with max priority(minimal value) works slow in O(N)
import java.util.*;
public class PriorityQueue<K extends Comparable> {
private int index;
private Comparable[] elements;
public Object[] getElements() {
return elements;
}
public PriorityQueue(int capacity) {
if (capacity < 0)
capacity = 10;
elements = new Comparable[capacity];
}
public PriorityQueue() {
this(10);
}
public boolean isEmpty() {
return index == 0;
}
public int size() {
return index;
}
private void resize() {
elements = Arrays.copyOf(elements, elements.length * 2);
}
public void add(K element) {
if (index == elements.length)
resize();
elements[index++] = element;
}
public Comparable remove() {
if (isEmpty())
throw new PriorityQueueIsEmptyException("Queue is empty!");
int priorityIndex = 0;
for (int i = 1; i < index; i++) {
if (elements[i].compareTo(elements[priorityIndex]) < 0)
priorityIndex = i;
}
Comparable result = elements[priorityIndex];
index--;
elements[priorityIndex] = elements[index];
return result;
}
public Comparable<K> poll() {
if (isEmpty())
return null;
return remove();
}
public Comparable element() {
if (isEmpty())
throw new PriorityQueueIsEmptyException("Queue is empty!");
int priorityIndex = 0;
for (int i = 1; i < index; i++) {
if (elements[i].compareTo(elements[priorityIndex]) < 0)
priorityIndex = i;
}
return elements[priorityIndex];
}
public Comparable peek() {
if (isEmpty())
return null;
return element();
}
public Iterator iterator() {
return new QueueIterator();
}
public void print() {
for (int i = 0; i < index; i++) {
System.out.print(elements[i] + " --> ");
}
System.out.println();
}
private class QueueIterator implements Iterator {
// we keep list of indexes of elements that have been taken allready by method next()
// we keep it in order not to check elements with such indexes when we are founding new min element
// sorry for my eng
private List<Integer> usedIndexes;
private Comparable next;
public QueueIterator() {
usedIndexes = new ArrayList<Integer>();
}
private Comparable min(Comparable[] elements, int from, int to, List<Integer> usedIndexes) {
// trick to assign min value
// we cannot start from the first element cause he might be minimal allready
int startIndex = from;
for (int i = from; i <= to; i++) {
if (!usedIndexes.contains(i)) {
startIndex = i;
break;
}
}
Comparable min = elements[startIndex];
int minIndex = startIndex;
for (int i = from; i <= to; i++) {
if (!usedIndexes.contains(i) && elements[i].compareTo(min) < 0) {
min = elements[i];
minIndex = i;
}
}
usedIndexes.add(minIndex);
return min;
}
#Override
public boolean hasNext() {
return usedIndexes.size() == index;
}
#Override
public Comparable next() {
if (isEmpty())
throw new NoSuchElementException();
next = min(elements, 0, index - 1, usedIndexes);
return next;
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
}
}
public class PriorityQueueIsEmptyException extends RuntimeException {
PriorityQueueIsEmptyException() {
}
PriorityQueueIsEmptyException(String message) {
super(message);
}
}
My questions are:
had I made iterator right?
it seems to me that its not good that method next(), which works in O(N * N), am I right?
is there any way to do iterator better?
This is something i don't understand, and my professor is busy this week so i can't ask her. Can someone explain to me how to set up a list iterator, and use it to return elements in an ArrayList? thanks. It is the the method "public Iterator iterator()", i've tried my best with it, but i can't complete it.
public class ArrayList<E> implements List<E> {
private E[] elementData;
private int elementCount;
private int capacityIncrement;
private static final int INVALID_INDEX=-1;
private static final int DEFAULT_CAPACITY = 100;
public ArrayList() {
capacityIncrement = 0;
elementData = (E[]) new Object[DEFAULT_CAPACITY];
}
public ArrayList(int capacity) {
this.capacityIncrement = 0;
this.elementData = (E[]) new Object[capacity];
}
public ArrayList(int capacity, int increment) {
this.capacityIncrement = increment;
this.elementData = (E[]) new Object[capacity];
}
public int size() {
return elementCount;
}
public boolean isEmpty() {
if (elementCount != 0) return false;
else return true;
}
public void clear() {
elementCount = 0;
}
public boolean contains(E element) { //check back
for (int i = 0; i < elementCount; i++) {
if (elementData[i].equals(element)) return true; //== vs. .equals
}
return false;
}
public void add(E element) {
elementCount++;
elementData[elementCount] = element;
}
public boolean remove(E element) {
for (int i = 0; i < elementCount; i++) { //while vs. loop
if (elementData[i].equals(element)) {
for (int j = 0; j <= (elementCount - i); j++){
elementData[i] = elementData[i++];
elementCount = elementCount - 1;
return true;
}
}
}
return false;
}
public E elementAt(int index) {
return elementData[index]; //elementdata vs. elementcount
}
public int indexOf(E element) {
for (int i = 0; i < elementCount; i++) //while vs. loop
if (elementData[i].equals(element)) {
return i;
} return INVALID_INDEX;
}
public void insertElementAt(E element, int index) {
elementCount = elementCount + 1;
for (int i = index; i < elementCount; i++) {
elementData[i++] = elementData[i];
}
elementData[index] = element;
//shift right (look at notes)
}
public void removeElementAt(int index) {
for (int i = index; i < elementCount; i++) {
elementData[i] = elementData[i++];
}
elementCount = elementCount - 1;
}
public void setElementAt(E element, int index) {
elementData[index] = element;
}
public void removeDuplicates() {
for (int i = 0; i < elementCount; i++) {
for (int j = 0; j < elementCount; j++) {
if (elementData[i].equals(elementData[j])) {
elementData[i] = elementData[i++];
elementCount = elementCount - 1;
}
}
}
}
public void trimToSize() { //don't need to add trims to removing methods??
}
public Iterator<E> iterator() {
Iterator itr = new list.iterator();
while (itr.hasNext()) {
}
/**
*
* #return a list iterator of the elements
* in this list (in proper sequence).
*/
}
public Iterator<E> iterator(int index) {
throw new UnsupportedOperationException("Not supported yet.");
}
private static class ArrayListIterator<E> implements Iterator<E> {
private ArrayListIterator(ArrayList c) {
/**
* Returns a list iterator of the elements in this list (in proper sequence).
* #param c list to be iterated upon
*/
elementData=c;
}
}
}
Iterator is just an interface that specifies an implementing class must provide next() and hasNext().
A simple first cut implementation would be to make your array list implement the Iterator interface.
You would add a "currentIndex" member and a method like
Iterator<E> iterator() { return this; }
next() and hasNext() would use the currentIndex and the array size as appropriate.
Obviously this breaks if you want to have more than one iterator over the same collection, so the next step would be to refactor the iterator stuff into a separate class.
In your public Iterator iterator() method you are returning an iterator. So
public Iterator<E> iterator() {
return this.iterator();
}
will do the job.