diff --git a/.gitignore b/.gitignore index fce5816..b340036 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.class +*.orig # Directories # /build/ diff --git a/Immutable_collections_java8_project/src/collections/implementations/DoubleLinkedListProxy.java b/Immutable_collections_java8_project/src/collections/implementations/DoubleLinkedListProxy.java new file mode 100644 index 0000000..98ce534 --- /dev/null +++ b/Immutable_collections_java8_project/src/collections/implementations/DoubleLinkedListProxy.java @@ -0,0 +1,106 @@ +package collections.implementations; + +import java.util.function.Function; +import java.util.function.UnaryOperator; + +public class DoubleLinkedListProxy /* implements List */ { + + /** The list we keep track of */ + private VersionedDoubleLinkedList versionedList; + + /** The first cell of the list */ + private ListCell cell; + + /** Version of the list this proxy should be wrapping */ + private int version; + + public DoubleLinkedListProxy() { + this(new VersionedDoubleLinkedList()); + } + + public DoubleLinkedListProxy(VersionedDoubleLinkedList versionedList) { + this.versionedList = versionedList; + this.cell = versionedList.getFirstCell(); + this.version = versionedList.getVersion(); + } + + public DoubleLinkedListProxy(VersionedDoubleLinkedList versionedList, + ListCell cell) { + this.versionedList = versionedList; + this.cell = cell; + this.version = versionedList.getVersion(); + } + + public DoubleLinkedListProxy nil() { // List + return new DoubleLinkedListProxy(); + } + + public boolean isEmpty() { + return versionedList.isEmpty(cell, version); + } + + public DoubleLinkedListProxy cons(E head) { // List + this.versionedList.addFirst(head, cell, version); + return new DoubleLinkedListProxy(versionedList, cell.getPrevious()); + } + + public DoubleLinkedListProxy tail() { // List + ListCell tailCell = versionedList.tail(cell, version); + return new DoubleLinkedListProxy(versionedList, tailCell); + } + + public E head() { + return this.versionedList.head(this.cell, this.version); + } + + public DoubleLinkedListProxy concat(DoubleLinkedListProxy that) { // List list + if (!(that instanceof DoubleLinkedListProxy)) + throw new UnsupportedOperationException(); + + DoubleLinkedListProxy thatList = (DoubleLinkedListProxy) that; + ListCell newCell = versionedList.concatenate(cell, + version, + thatList.versionedList, + thatList.cell, + thatList.version); + return new DoubleLinkedListProxy(versionedList, newCell); + } + + public DoubleLinkedListProxy reverse() { // List + this.versionedList.reverse(cell, version); + return new DoubleLinkedListProxy(versionedList, cell); + } + + public DoubleLinkedListProxy map(Function fctn) { // List + VersionedDoubleLinkedList newVersionedList = versionedList.map(cell, version, fctn); + return new DoubleLinkedListProxy(newVersionedList, newVersionedList.getFirstCell()); + } + + public DoubleLinkedListProxy endoMap(UnaryOperator op) { // List + versionedList.applyMap(cell, version, op); + return new DoubleLinkedListProxy(versionedList, cell); + } + + public String toString() { + return this.versionedList.toString(cell, version); + } + + public boolean equals(Object obj) { + if (!(obj instanceof DoubleLinkedListProxy)) { // List + return false; + } + if (obj instanceof DoubleLinkedListProxy) { + DoubleLinkedListProxy thatList = (DoubleLinkedListProxy) obj; + return versionedList.isEqual(cell, + version, + thatList.versionedList, + thatList.cell, + thatList.version); + } + // else { + // List thatList = (List) obj; // List list + // return versionedList.isEqual(cell, version, thatList); + // } + return false; // to suppr + } +} diff --git a/Immutable_collections_java8_project/src/collections/implementations/ImmutableArrayList.java b/Immutable_collections_java8_project/src/collections/implementations/ImmutableArrayList.java index 9db5125..54e11ab 100644 --- a/Immutable_collections_java8_project/src/collections/implementations/ImmutableArrayList.java +++ b/Immutable_collections_java8_project/src/collections/implementations/ImmutableArrayList.java @@ -1,34 +1,18 @@ package collections.implementations; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Optional; -import java.util.function.BinaryOperator; -import java.util.function.Function; -import java.util.function.Predicate; import collections.interfaces.ImmutableList; -public class ImmutableArrayList implements ImmutableList +public class ImmutableArrayList extends ImmutableBaseIterativeList implements ImmutableList { - private final E[] _array; - private final int _length; - - /** * Constructs an empty list with an initial capacity of 0. */ - @SuppressWarnings("unchecked") public ImmutableArrayList () { - _array = (E[]) new Object[0]; - _length = 0; + super(); } /** @@ -39,18 +23,12 @@ public ImmutableArrayList () @SuppressWarnings("unchecked") public ImmutableArrayList (E... elems) { - if (elems == null) - throw new NullPointerException(); - else - { - _array = elems; - _length = _array.length; - } + super(elems); } + + + - public ImmutableList create(E[] elems) { - return new ImmutableArrayList(elems); - } /** *

Constructs a list containing the elements of the specified * collection, in the order they are returned by the collection's @@ -60,138 +38,39 @@ public ImmutableList create(E[] elems) { * * @param elems - the collection whose elements are to be placed into this list */ - @SuppressWarnings("unchecked") public ImmutableArrayList(Collection elems) { - if (elems == null) - throw new NullPointerException(); - else - { - _array = (E[])elems.toArray(); - _length = _array.length; - } + super(elems); } - /** - * Private accessor to get the inner array. - * @return the inner array. - */ - private E[] getArray() { - return _array; - } - - class ImmutableArrayListIterator implements Iterator { - - /** Current node pointed by the iterator */ - private int index; - private int size; - - /** - * Create a new iterator starting from the beginning of the linked list. - */ - public ImmutableArrayListIterator() { - index = 0; - size = size(); - } - - public boolean hasNext() { - return index <= size-1 ? true : false; - } - - public E next() throws NoSuchElementException { - if(index >= size) - throw new NoSuchElementException(); - - E elem = getArray()[index]; - ++index; - return elem; - } - - public void remove() throws - UnsupportedOperationException, - IllegalStateException { - throw new UnsupportedOperationException(); - } - } - - public Iterator iterator() { - return new ImmutableArrayListIterator(); + + + public ImmutableArrayList create(E[] elems) { + return new ImmutableArrayList(elems); } - public int size() { - return _length; + public ImmutableArrayList create(Collection elems) { + return new ImmutableArrayList(elems); } - public E get(int index) { - if (index < 0 || index >= size()) - throw new IndexOutOfBoundsException(); - else - return _array[index]; - - } - public int indexOf(E elem) { - int i = 0; - for (E other : this) - if (equals(elem, other)) - return i; - else - ++i; - return -1; - } @Override - public ImmutableList subList(int fromIndex, int toIndex) + public ImmutableArrayList subList(int fromIndex, int toIndex) throws IndexOutOfBoundsException, IllegalArgumentException { if (fromIndex < 0 || toIndex > size()) throw new IndexOutOfBoundsException(); if (fromIndex > toIndex) throw new IllegalArgumentException(); if (fromIndex == toIndex) - return new ImmutableLinkedList(); + return new ImmutableArrayList(); - return new SubList(fromIndex, toIndex - fromIndex); - } - - class SubList extends ImmutableArrayList - { - transient final int offset; - transient final int length; - - SubList(int offset, int length) { - this.offset = offset; - this.length = length; - } - - @Override - public int size() { - return length; - } - - @Override - public E get(int index) { - if (index < 0 || index >= length) - throw new IndexOutOfBoundsException(); - return ImmutableArrayList.this.get(index + offset); - } - - @Override - public ImmutableList subList(int fromIndex, int toIndex) { - if (fromIndex < 0 || toIndex < fromIndex || toIndex > length) - throw new IndexOutOfBoundsException(); - return ImmutableArrayList.this.subList(fromIndex + offset, toIndex + offset); - } - } - - - @Override - public ImmutableList reverse() { int j = 0; @SuppressWarnings("unchecked") - E[] res = (E[]) new Object[size()]; - for(int i= size()-1; i >= 0; --i) + E[] res = (E[]) new Object[toIndex - fromIndex]; + for(int i= fromIndex; i < toIndex; ++i) { res[j] = get(i); ++j; @@ -199,154 +78,13 @@ public ImmutableList reverse() { return new ImmutableArrayList(res); } - - public ImmutableList sort(Comparator comparator) { - E[] a = toArray(); - Arrays.sort(a,(Comparator) comparator); - return new ImmutableLinkedList(a); - } - - public boolean contains(E elem) { - return any((E other) -> equals(elem, other)); - } - - public boolean containsAll(Collection elems) { - return containsAll(new ImmutableArrayList(elems)); - } - - public boolean containsAll(ImmutableList elems) { - return elems.all((E elem) -> contains(elem)); - } - - @SuppressWarnings("unchecked") - public boolean containsAll(E... elems) { - return containsAll(new ImmutableArrayList(elems)); - } - - - public boolean any(Predicate predicate) { - for (E elem : this) - if (predicate.test(elem)) - return true; - return false; - } - - - public boolean all(Predicate predicate) { - for (E elem : this) - if (!predicate.test(elem)) - return false; - return true; - } - - - public ImmutableList cons(E elem) { - @SuppressWarnings("unchecked") - E[] elems = (E[]) new Object[size()+1]; - elems[0] = elem; - - int i = 1; - for (E e : this) { - elems[i] = e; - ++i; - } - - return new ImmutableArrayList(elems); - } - - - public ImmutableList concat(Collection elems) { - ImmutableList list = this; - for (E elem: elems){ - list = list.concat(elem); - } - return list; - } - - - public ImmutableList concat(ImmutableList elems) { - ImmutableList list = this; - for (E elem : elems) { - list = list.concat(elem); - } - return list; - } - - @SuppressWarnings({"unchecked"}) - public ImmutableList concat(E... elems){ - ImmutableList list = this; - for (int i = 0 ; i concat(E elem) { - @SuppressWarnings("unchecked") - E[] elems = (E[]) new Object[size() + 1]; - int i = 0; - for (E e : this) { - elems[i] = e; - ++i; - } - elems[size()] = elem; - return new ImmutableLinkedList(elems); - } - - - public ImmutableList remove(Collection elems) { - ImmutableList list = this; - for (E elem: elems){ - list = list.remove(elem); - } - return list; - } - - - public ImmutableList remove(ImmutableList elems) { - ImmutableList list = this; - for (E elem : elems) { - list = list.remove(elem); - } - return list; - } - - @SuppressWarnings("unchecked") - public ImmutableList remove(E... elems) { - ImmutableList list = this; - for (int i = 0 ; i remove(E elem) { - E[] newElems; - int i; - boolean remove; - newElems = (E[]) new Object[size() - 1]; - i = 0; - remove = false; - for ( E e :this){ - if(!remove && equals(elem,e)) - remove = true; - else{ - if (i == this.size()-1) - throw new IllegalArgumentException(); - newElems[i] = e; - i++; - } - } - - return new ImmutableLinkedList(newElems); + @Override + public ImmutableArrayList reverse() { + return new ImmutableReversedArrayList(this); } - @SuppressWarnings("unchecked") - public ImmutableList remove(int index) { //TODO + public ImmutableArrayList remove(int index) { E[] newElems; int i; boolean remove; @@ -365,170 +103,24 @@ public ImmutableList remove(int index) { //TODO ++i; } } - return new ImmutableLinkedList(newElems); + return new ImmutableArrayList(newElems); } - - public ImmutableList union(Collection elems) { - // TODO Auto-generated method stub - return null; - } - - - public ImmutableList union(ImmutableList elems) { - // TODO Auto-generated method stub - return null; - } - - @SuppressWarnings("unchecked") - public ImmutableList union(E... elems) { - // TODO Auto-generated method stub - return null; - } - - - public ImmutableList intersect(Collection elems) { - // TODO Auto-generated method stub - return null; - } - - - public ImmutableList intersect(ImmutableList elems) { - // TODO Auto-generated method stub - return null; - } - - - @SuppressWarnings("unchecked") - public ImmutableList intersect(E... elems) { - // TODO Auto-generated method stub - return null; - } - - - public ImmutableList map(Function mapper) { + + public ImmutableArrayList cons(E elem) { @SuppressWarnings("unchecked") - F[] elems = (F[]) new Object[size()]; - int i = 0; - for (E elem : this) { - elems[i] = mapper.apply(elem); - ++i; - } - - return new ImmutableArrayList(elems); - } - - - @Override - public ImmutableList filter(Predicate predicate) { - ImmutableList res = new ImmutableArrayList(); - for (E elem : this) - if (predicate.test(elem)) - res = res.concat(elem); - return res; - } - - - - public Optional reduce(BinaryOperator accumulator) { - switch (size()) { - case 0 : return Optional.empty(); - case 1 : return Optional.of(get(0)); - default : - - E result = get(0); - for (E elem : subList(1, size())) { - result = accumulator.apply(result, elem); - } - return Optional.of(result); - } - } - - /** - * Hash an object. - * - * @param o the object to hash - * @return o1 == null ? 0 : o1.hashCode() - */ - static final int hashCode(Object o) { - return o == null ? 0 : o.hashCode(); - } - - public int hashCode() { - int hashCode = 1; - Iterator itr = iterator(); - int pos = size(); - while (--pos >= 0) - hashCode = 31 * hashCode + hashCode(itr.next()); - return hashCode; - } - - public E[] toArray() { - return getArray(); - } - - @SuppressWarnings("hiding") - @Override - public E[] toArray(E[] a) { - return a; - } - - public List asList() { - List al = new ArrayList(size()); - for(E e : this) - al.add(e); - return al; - } - - /** - * Compare two objects according to Collection semantics. - * - * @param o1 the first object - * @param o2 the second object - * @return o1 == null ? o2 == null : o1.equals(o2) - */ - static final boolean equals(Object o1, Object o2) { - return o1 == null ? o2 == null : o1.equals(o2); - } - - public boolean equals(Object o) { - if (! (o instanceof ImmutableList)) - return false; - - @SuppressWarnings("rawtypes") - ImmutableList other = (ImmutableList) o; - - if (size() != other.size()) - return false; - - Iterator it1 = iterator(); - @SuppressWarnings("rawtypes") - Iterator it2 = other.iterator(); + E[] elems = (E[]) new Object[size()+1]; + elems[0] = elem; - while (it1.hasNext()) { - if (!equals(it1.next(), it2.next())) - return false; + int i = 1; + for (E e : this) { + elems[i] = e; + ++i; } - return true; - } - - public E head() throws NoSuchElementException { - if(_length == 0) - return null; - return _array[0]; - } - - public ImmutableList tail() throws UnsupportedOperationException { - return subList(1, _length); - } - - public E last() throws NoSuchElementException { - return _array[_length-1]; + return new ImmutableArrayList(elems); } - public ImmutableList clone() { - return subList(0, _length); - } + } diff --git a/Immutable_collections_java8_project/src/collections/implementations/ImmutableBaseInductiveList.java b/Immutable_collections_java8_project/src/collections/implementations/ImmutableBaseInductiveList.java new file mode 100644 index 0000000..805ee5c --- /dev/null +++ b/Immutable_collections_java8_project/src/collections/implementations/ImmutableBaseInductiveList.java @@ -0,0 +1,284 @@ +package collections.implementations; + +import java.util.Collection; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import collections.interfaces.ImmutableCoreList; +import collections.interfaces.InductiveList; + + + +class Node { + + /** The element in the list */ + private final E element; + + /** The next list node, null if this is last */ + private final Node next; + + public Node(E element, Node next) { + this.element=element; + this.next=next; + } + + public Node(E element) { + this(element, null); + } + + /** + * Returns the element in the node. + * + * @returns the element in the node. + */ + public E getElement() { + return this.element; + } + + /** Returns the next list node, null if this is last. + * + * @returns the next list node, null if this is last + */ + public Node getNext() { + return next; + } + + /** Returns whether this node is followed by another one. + * + * @returns true if this node is followed by another one. + */ + public boolean hasNext() { + return getNext() != null; + } +} + +public abstract class ImmutableBaseInductiveList implements InductiveList { + + /** The first node element of the list. */ + protected final Node head; + + /** The last node element of the list. */ + protected final Node last; + + /** The number of elements in this list. */ + protected final int size; + + + /** + * Internal constructor which create a linked list given its attributes. + * + * @param head The first node of the list + * @param last The last node of the list + * @param size The size of the list + */ + public ImmutableBaseInductiveList(Node head, Node last, int size) { + this.head = head; + this.last = last; + this.size = size; + } + + /** + * Create a empty linked list. + */ + public ImmutableBaseInductiveList() { + this(null, null, 0); + } + + /** + * Create a linked list containing the given elements in order. + * + * @param elems collection of elements to populate this list from + * @throws NullPointerException if elems is null + */ + @SuppressWarnings("unchecked") + public ImmutableBaseInductiveList(Collection elems) { + this((E[])elems.toArray()); + } + + /** + * Create a linked list containing the given elements in order. + * + * @param elems the elements to populate this list from + * @throws NullPointerException if elems is null + */ + @SuppressWarnings({"unchecked"}) + public ImmutableBaseInductiveList(E... elems) { + if (elems == null) + throw new NullPointerException(); + + if (elems.length == 0) { + this.head = null; + this.last = null; + this.size = 0; + return; + } + + Node head = new Node(elems[elems.length - 1]); + this.last = head; + + for (int i = elems.length - 2 ; i >=0 ; --i) + head = new Node(elems[i], head); + + this.head = head; + this.size = elems.length; + } + + + + + + /** + * Returns the first node element of the list. + * + * @returns the first node element of the list. + **/ + protected Node headNode() { + return head; + } + + /** + * Returns the last node element of the list. + * + * @returns the last node element of the list. + **/ + protected Node lastNode() { + return last; + } + + protected int size() { + return size; + } + + @Override + public InductiveList clone() { + return (InductiveList) ImmutableCoreList.clone(this); + } + + @Override + public boolean equals(Object o) { + return ImmutableCoreList.equals(this, o); + } + + @Override + public int hashCode() { + return ImmutableCoreList.hashCode(this); + } + + @Override + public InductiveList cons(E elem) { + return create(new Node(elem, headNode()), + lastNode(), + size() + 1); + } + + @Override + public E head() throws NoSuchElementException { + if (isEmpty()) + throw new NoSuchElementException(); + else + return headNode().getElement(); + } + + + @Override + public InductiveList tail() { + if (isEmpty()) + throw new UnsupportedOperationException(); + else + { + final int fromIndex = 1; + final int toIndex = size(); + if (fromIndex < 0 || toIndex > size()) + throw new IndexOutOfBoundsException(); + if (fromIndex > toIndex) + throw new IllegalArgumentException(); + if (fromIndex == toIndex) + return new ImmutableLinkedList(); + + int i = 0; + Node node = headNode(); + while (i != fromIndex) { + node = node.getNext(); + ++i; + } + Node subListHead = node; + + while (i != toIndex-1) { + node = node.getNext(); + ++i; + } + Node subListLast = node; + + return create(subListHead, + subListLast, + toIndex - fromIndex); + } + } + + public abstract ImmutableLinkedList create(Node from, Node head, int size); + + @Override + public E last() throws NoSuchElementException { + if (isEmpty()) + throw new NoSuchElementException(); + else + return lastNode().getElement(); + } + + + + @Override + public Iterator iterator() { + return new ImmutableLinkedListIterator(); + } + + + + @Override + public boolean isEmpty() { + return head==null; + } + + // Iterators & streams + + class ImmutableLinkedListIterator implements Iterator { //TODO change name ? + + /** Current node pointed by the iterator */ + private Node currentNode; + + /** Tell whether the iterator can continue or not */ + private boolean hasNext; + + /** + * Create a new iterator starting from the beginning of the linked list. + */ + public ImmutableLinkedListIterator() { + currentNode = headNode(); + hasNext = (size() != 0); + } + + public boolean hasNext() { + return hasNext; + } + + public E next() throws NoSuchElementException { + if (!hasNext()) + throw new NoSuchElementException(); + + E elem = currentNode.getElement(); + if (currentNode == lastNode()) + hasNext = false; + else + currentNode = currentNode.getNext(); + return elem; + } + + public void remove() throws + UnsupportedOperationException, + IllegalStateException { + throw new UnsupportedOperationException(); + } + } +} + + diff --git a/Immutable_collections_java8_project/src/collections/implementations/ImmutableBaseIterativeList.java b/Immutable_collections_java8_project/src/collections/implementations/ImmutableBaseIterativeList.java new file mode 100644 index 0000000..855e54a --- /dev/null +++ b/Immutable_collections_java8_project/src/collections/implementations/ImmutableBaseIterativeList.java @@ -0,0 +1,152 @@ +package collections.implementations; + +import java.util.Collection; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import collections.interfaces.ImmutableCoreList; +import collections.interfaces.IterativeList; + + +public abstract class ImmutableBaseIterativeList implements IterativeList +{ + + protected final E[] _array; + protected final int _length; + + + + /** + * Constructs an empty list with an initial capacity of 0. + */ + @SuppressWarnings("unchecked") + public ImmutableBaseIterativeList() + { + _array = (E[]) new Object[0]; + _length = 0; + } + + /** + *

Constructs a list containing the given elements + *

If the specified collection is null, constructs an empty ArrayList with a capacity of 0. + * @param elems - the collection whose elements are to be placed into this list + */ + @SuppressWarnings("unchecked") + public ImmutableBaseIterativeList (E... elems) + { + if (elems == null) + throw new NullPointerException(); + else if (elems.length == 0) { + this._array = (E[]) new Object[0]; + this._length = 0; + } + else + { + _array = elems; + _length = _array.length; + } + } + + + /** + *

Constructs a list containing the elements of the specified + * collection, in the order they are returned by the collection's + * iterator. + *

If the specified collection is null, constructs an empty ArrayList + * with a capacity of 0. + * + * @param elems - the collection whose elements are to be placed into this list + */ + @SuppressWarnings("unchecked") + public ImmutableBaseIterativeList(Collection elems) + { + if (elems == null) + throw new NullPointerException(); + else + { + _array = (E[])elems.toArray(); + _length = _array.length; + } + } + + + /** + * Private accessor to get the inner array. + * @return the inner array. + */ + protected E[] getArray() { + return _array; + } + + + + @Override + public E get(int index) throws IndexOutOfBoundsException { + if (index < 0 || index >= size()) + throw new IndexOutOfBoundsException(); + if(index >=0 && index < size()) + return _array[index]; + else + return null; + } + + @Override + public boolean equals(Object o) { + return IterativeList.equals(this, o); + } + + @Override + public ImmutableCoreList clone() { + return ImmutableCoreList.clone(this); + } + + @Override + public int hashCode() { + return ImmutableCoreList.hashCode(this); + } + + @Override + public Iterator iterator() { + return new ImmutableArrayListIterator(); + } + + @Override + public int size() { + return _length; + } + + class ImmutableArrayListIterator implements Iterator { + + /** Current node pointed by the iterator */ + private int index; + private int size; + + /** + * Create a new iterator starting from the beginning of the list. + */ + public ImmutableArrayListIterator() { + index = 0; + size = size(); + } + + public boolean hasNext() { + return index <= size-1 ? true : false; + } + + public E next() throws NoSuchElementException { + if(index >= size) + throw new NoSuchElementException(); + + E elem = _array[index]; + ++index; + return elem; + } + + public void remove() throws + UnsupportedOperationException, + IllegalStateException { + throw new UnsupportedOperationException(); + } + } + +} diff --git a/Immutable_collections_java8_project/src/collections/implementations/ImmutableLinkedList.java b/Immutable_collections_java8_project/src/collections/implementations/ImmutableLinkedList.java index 90a383c..6db34c4 100644 --- a/Immutable_collections_java8_project/src/collections/implementations/ImmutableLinkedList.java +++ b/Immutable_collections_java8_project/src/collections/implementations/ImmutableLinkedList.java @@ -1,98 +1,12 @@ package collections.implementations; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Optional; -import java.util.Spliterator; -import java.util.Spliterators; -import java.util.function.BinaryOperator; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; import collections.interfaces.ImmutableList; -class Node { +public class ImmutableLinkedList extends ImmutableBaseInductiveList implements ImmutableList{ - /** The element in the list */ - private final E element; - /** The next list node, null if this is last */ - private final Node next; - - public Node(E element, Node next) { - this.element=element; - this.next=next; - } - - public Node(E element) { - this(element, null); - } - - /** - * Returns the element in the node. - * - * @returns the element in the node. - */ - public E getElement() { - return this.element; - } - - /** Returns the next list node, null if this is last. - * - * @returns the next list node, null if this is last - */ - public Node getNext() { - return next; - } - - /** Returns whether this node is followed by another one. - * - * @returns true if this node is followed by another one. - */ - public boolean hasNext() { - return getNext() != null; - } -} - -public class ImmutableLinkedList implements ImmutableList { - - /** The first node element of the list. */ - private final Node head; - - /** The last node element of the list. */ - private final Node last; - - /** The number of elements in this list. */ - private final int size; - - /** - * Returns the first node element of the list. - * - * @returns the first node element of the list. - **/ - private Node headNode() { - return head; - } - - /** - * Returns the last node element of the list. - * - * @returns the last node element of the list. - **/ - private Node lastNode() { - return last; - } - - public int size() { - return size; - } // Constructors @@ -104,9 +18,7 @@ public int size() { * @param size The size of the list */ private ImmutableLinkedList(Node head, Node last, int size) { - this.head = head; - this.last = last; - this.size = size; + super(head, last, size); } /** @@ -135,25 +47,36 @@ public ImmutableLinkedList(Collection elems) { */ @SuppressWarnings({"unchecked"}) public ImmutableLinkedList(E... elems) { - if (elems == null) - throw new NullPointerException(); + super(elems); + } - Node head = new Node(elems[elems.length - 1]); - this.last = head; - for (int i = elems.length - 2 ; i >=0 ; --i) - head = new Node(elems[i], head); - this.head = head; - this.size = elems.length; + @Override + public ImmutableLinkedList create(E[] elems) { + return new ImmutableLinkedList(elems); } - public ImmutableList create(E[] elems) { - return new ImmutableLinkedList(elems); + @Override + public ImmutableLinkedList create(Collection elems) { + return new ImmutableLinkedList(elems); } + @Override + public ImmutableLinkedList create(Node from, Node head, int size){ + return new ImmutableLinkedList(from, head, size); + } + + + // Operations + + public int size() { + return size; + } + + public E get(int index) throws IndexOutOfBoundsException { if (index < 0 || index >= size()) throw new IndexOutOfBoundsException(); @@ -168,39 +91,7 @@ public E get(int index) throws IndexOutOfBoundsException { return null; // Never happens } - public int indexOf(E elem) { - int i = 0; - for (E other : this) - if (equals(elem, other)) - return i; - else - ++i; - return -1; - } - - public E head() throws NoSuchElementException { - if (isEmpty()) - throw new NoSuchElementException(); - else - return headNode().getElement(); - } - - public ImmutableList tail() throws UnsupportedOperationException { - if (isEmpty()) - throw new UnsupportedOperationException(); - else - return subList(1, size()); - } - - public E last() throws NoSuchElementException { - if (isEmpty()) - throw new NoSuchElementException(); - else - return lastNode().getElement(); - } - - @SuppressWarnings("unchecked") - public ImmutableList subList(int fromIndex, int toIndex) throws + public ImmutableLinkedList subList(int fromIndex, int toIndex) throws IndexOutOfBoundsException, IllegalArgumentException { @@ -217,148 +108,22 @@ public ImmutableList subList(int fromIndex, int toIndex) throws node = node.getNext(); ++i; } + Node subListHead = node; - E[] elems = (E[]) new Object[toIndex - fromIndex]; - while (i != toIndex) { - elems[i - fromIndex] = (E)node.getElement(); + while (i != toIndex-1) { node = node.getNext(); ++i; } + Node subListLast = node; - return new ImmutableLinkedList(elems); - } - - public ImmutableList reverse() { - if (isEmpty()) - return this; - else - return tail().reverse().concat(head()); - } - - public boolean contains(E elem) { - return any((E other) -> equals(elem, other)); - } - - public boolean containsAll(Collection elems) { - return containsAll(new ImmutableLinkedList(elems)); - } - - public boolean containsAll(ImmutableList elems) { - return elems.all((E elem) -> contains(elem)); - } - - public @SuppressWarnings({"unchecked"}) - boolean containsAll(E... elems) { - return containsAll(new ImmutableLinkedList(elems)); - } - - public boolean any(Predicate predicate) { - for (E elem : this) - if (predicate.test(elem)) - return true; - return false; - } - - public boolean all(Predicate predicate) { - for (E elem : this) - if (!predicate.test(elem)) - return false; - return true; - } - - // Factories - - public ImmutableList cons(E elem) { - return new ImmutableLinkedList(new Node(elem, headNode()), - lastNode(), - size() + 1); - } - - public ImmutableList concat(Collection elems){ - ImmutableList list = this; - for (E elem: elems){ - list = list.concat(elem); - } - return list; - } - public ImmutableList concat(ImmutableList elems) { - ImmutableList list = this; - for (E elem : elems) { - list = list.concat(elem); - } - return list; - } - @SuppressWarnings({"unchecked"}) - public ImmutableList concat(E... elems){ - ImmutableList list = this; - for (int i = 0 ; i concat(E elem) { - E[] elems = (E[]) new Object[size() + 1]; - int i = 0; - for (E e : this) { - elems[i] = e; - ++i; - } - elems[size()] = elem; - return new ImmutableLinkedList(elems); - } - - public ImmutableList remove(Collection elems) { - ImmutableList list = this; - for (E elem: elems){ - list = list.remove(elem); - } - return list; - - } - - public ImmutableList remove(ImmutableList elems) { - ImmutableList list = this; - for (E elem : elems) { - list = list.remove(elem); - } - return list; - } - - @SuppressWarnings({"unchecked"}) - public ImmutableList remove(E... elems) { - ImmutableList list = this; - for (int i = 0 ; i (subListHead, + subListLast, + toIndex - fromIndex); } - @SuppressWarnings("unchecked") - public ImmutableList remove(E elem) { - E[] newElems; - int i; - boolean remove; - newElems = (E[]) new Object[size() - 1]; - i = 0; - remove = false; - for ( E e :this){ - if(!remove && equals(elem,e)) - remove = true; - else{ - if (i == this.size()-1) - throw new IllegalArgumentException(); - newElems[i] = e; - i++; - } - } - - return new ImmutableLinkedList(newElems); - } @SuppressWarnings("unchecked") - public ImmutableList remove(int index) { + public ImmutableLinkedList remove(int index) { E[] newElems; int i; boolean remove; @@ -369,7 +134,7 @@ public ImmutableList remove(int index) { newElems = (E[]) new Object[size() -1]; i = 0; remove = false; - for ( E e :this){ + for ( E e : this){ if(!remove && i==index) remove = true; else{ @@ -380,159 +145,17 @@ public ImmutableList remove(int index) { return new ImmutableLinkedList(newElems); } - @SuppressWarnings("unchecked") - public ImmutableList map(Function mapper) { - F[] elems = (F[]) new Object[size()]; - int i = 0; - for (E elem : this) { - elems[i] = mapper.apply(elem); - ++i; - } - - return new ImmutableLinkedList(elems); - } - - public ImmutableList filter(Predicate predicate) { - ImmutableList res = new ImmutableLinkedList(); - for (E elem : this) - if (predicate.test(elem)) - res = res.concat(elem); - return res; - } - - public Optional reduce(BinaryOperator accumulator) { - switch (size()) { - case 0 : return Optional.empty(); - case 1 : return Optional.of(head()); - default : - - E result = head(); - for (E elem : tail()) { - result = accumulator.apply(result, elem); - } - return Optional.of(result); - } - } - - // Iterators & streams - - class ImmutableLinkedListIterator implements Iterator { - - /** Current node pointed by the iterator */ - private Node currentNode; - - /** - * Create a new iterator starting from the beginning of the linked list. - */ - public ImmutableLinkedListIterator() { - currentNode = headNode(); - } - - public boolean hasNext() { - return currentNode != null; - } - - public E next() throws NoSuchElementException { - if (currentNode == null) - throw new NoSuchElementException(); - - E elem = currentNode.getElement(); - currentNode = currentNode.getNext(); - return elem; - } - - public void remove() throws - UnsupportedOperationException, - IllegalStateException { - throw new UnsupportedOperationException(); - } - } - - public Iterator iterator() { - return new ImmutableLinkedListIterator(); - } - - public boolean equals(Object o) { - if (! (o instanceof ImmutableList)) - return false; - - @SuppressWarnings("rawtypes") - ImmutableList other = (ImmutableList) o; - - if (size() != other.size()) - return false; - - Iterator it1 = iterator(); - @SuppressWarnings("rawtypes") - Iterator it2 = other.iterator(); - - while (it1.hasNext()) { - if (!equals(it1.next(), it2.next())) - return false; - } - - return true; - } - - /** - * Compare two objects according to Collection semantics. - * - * @param o1 the first object - * @param o2 the second object - * @return o1 == null ? o2 == null : o1.equals(o2) - */ - static boolean equals(Object o1, Object o2) { - return o1 == null ? o2 == null : o1.equals(o2); - } - - /** - * Hash an object. - * - * @param o the object to hash - * @return o1 == null ? 0 : o1.hashCode() - */ - static int hashCode(Object o) { - return o == null ? 0 : o.hashCode(); - } - - public int hashCode() { - int hashCode = 1; - Iterator itr = iterator(); - int pos = size(); - while (--pos >= 0) - hashCode = 31 * hashCode + hashCode(itr.next()); - return hashCode; - } - - // Conversions - @SuppressWarnings("unchecked") - public E[] toArray(){ - return toArray((E[]) new Object[size()]); - } - - @SuppressWarnings({ "unchecked", "hiding" }) - public E[] toArray(E[] a){ - int i; - E[] result; - i=0; - result = a ; - for (Node x = (Node) this.head; x != null; x = x.getNext()){ - result[i++] = x.getElement(); - } - return a; + + @Override + public ImmutableLinkedList tail() { + return (ImmutableLinkedList) super.tail(); } - public List asList(){ - List myList = new ArrayList(); - - for (E e : this){ - myList.add(e); - } - return myList; - } - - public ImmutableList clone() { - return subList(0, size()); - } + + + @Override + public ImmutableLinkedList cons(E elem) { + return (ImmutableLinkedList) super.cons(elem); + } } diff --git a/Immutable_collections_java8_project/src/collections/implementations/ImmutableReversedArrayList.java b/Immutable_collections_java8_project/src/collections/implementations/ImmutableReversedArrayList.java new file mode 100644 index 0000000..19a5ca5 --- /dev/null +++ b/Immutable_collections_java8_project/src/collections/implementations/ImmutableReversedArrayList.java @@ -0,0 +1,117 @@ +package collections.implementations; + +import java.util.List; +import java.util.Collections; +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class ImmutableReversedArrayList extends ImmutableArrayList { + + /** The encapsulated list we delegate things to. */ + private final ImmutableArrayList list; + + /** + * Construct a reverse view of the given list. + * + * @param list the list to be reversed. + */ + public ImmutableReversedArrayList(ImmutableArrayList list) { + this.list = list; + } + + public int size() { + return list.size(); + } + + /** + * Return equivalent of index counting from the end to simulate the + * reversed view of the list. + * + * @param index The index to be reversed + **/ + private int reverseIndex(int index) { + return size() - 1 - index; + } + + public E get(int index) throws IndexOutOfBoundsException { + return list.get(reverseIndex(index)); + } + + public int indexOf(E elem) { + int index = list.indexOf(elem); + if (index != -1) + index = reverseIndex(index); + return index; + } + + public E head() throws NoSuchElementException { + return list.last(); + } + + public E last() throws NoSuchElementException { + return list.head(); + } + + + public ImmutableArrayList subList(int fromIndex, int toIndex) throws + IndexOutOfBoundsException, + IllegalArgumentException { + if (fromIndex == toIndex) + return new ImmutableArrayList(); + + return list.subList(reverseIndex(toIndex -1), + reverseIndex(fromIndex-1)).reverse(); + } + + public ImmutableArrayList reverse() { + return list; + } + + + public ImmutableArrayList remove(int index) { + return list.remove(reverseIndex(index)).reverse(); + } + + class ReversedListIterator implements Iterator { + + /** Current index pointed by the iterator */ + private int index; + + /** + * Create a new iterator starting from the beginning of the list. + */ + public ReversedListIterator() { + index = size()-1; + } + + public boolean hasNext() { + return index >= 0 ? true : false; + } + + public E next() throws NoSuchElementException { + if (!hasNext()) + throw new NoSuchElementException(); + + E elem = list.get(index); + --index; + return elem; + } + + public void remove() throws + UnsupportedOperationException, + IllegalStateException { + throw new UnsupportedOperationException(); + } + } + + public Iterator iterator() { + return new ReversedListIterator(); + } + + @SuppressWarnings("unchecked") + public E[] toArray() { + List tmp = list.asList(); + Collections.reverse(tmp); + return (E[]) tmp.toArray(); + } +} diff --git a/Immutable_collections_java8_project/src/collections/implementations/ListCell.java b/Immutable_collections_java8_project/src/collections/implementations/ListCell.java new file mode 100644 index 0000000..d47c961 --- /dev/null +++ b/Immutable_collections_java8_project/src/collections/implementations/ListCell.java @@ -0,0 +1,265 @@ +package collections.implementations; + +import java.util.function.Function; +import java.util.function.UnaryOperator; + +// import collections.interfaces.InductiveIterativeList; +// import collections.interfaces.IterativeList; +// import collections.interfaces.ImmutableList; + +public abstract class ListCell { + + /** The cell before this one in the linked list */ + protected ListCell previous; + + /** The cell after this one in the linked list */ + protected ListCell next; + + final public ListCell getPrevious() { + return previous; + } + + final public void setPrevious(ListCell l) { + this.previous = l; + } + + public ListCell getNext() { + return this.next; + } + + final public void setNext(ListCell l) { + this.next = l; + } + + final public boolean isFirst() { + return this.getPrevious().isEmpty(); + } + + abstract public boolean isEmpty(); + abstract public E getItem(); + abstract public void setItem(E item); + + abstract public void concat(ListCell cell); + abstract public void reverse(ListCell nilCell); + abstract public ListCell clone(); + abstract public ListCell map(Function mapper); + abstract public void applyMap(UnaryOperator mapper); + + abstract public boolean isEqual(ListCell cell); + // abstract public boolean isEqual(List list); + + static void linkCells(ListCell first, ListCell second) { + first.next = second; + second.previous = first; + } +} + +final class NilCell extends ListCell { + + public NilCell() { + this.previous = this; + this.next = this; + } + + public boolean isEmpty() { + return true; + } + + public E getItem() { + throw new UnsupportedOperationException(); + } + + public void setItem(E item) { + throw new UnsupportedOperationException(); + } + + public void concat(ListCell cell) { + throw new UnsupportedOperationException(); + } + + public void reverse(ListCell nilCell) { } + + public void applyMap(UnaryOperator mapper) { } + + public ListCell map(Function mapper) { + return new NilCell(); + } + + public boolean isEqual(ListCell cell) { + return cell.isEmpty(); + } + + // public boolean isEqual(List list) { + // return cell.isEmpty(); + // } + + public NilCell clone() { + return new NilCell(); + } + + public String toString() { + return "[]"; + } +} + +class ConsCell extends ListCell { + + /** The element of this cell */ + private E item; + + public ConsCell(E head, ListCell tail) { + setItem(head); + this.next = tail; + this.previous = tail.previous; + tail.previous = this; + this.previous.next = this; + } + + private ConsCell(E item) { + this.item = item; + } + + public boolean isEmpty() { + return false; + } + + public E getItem() { + return item; + } + + public void setItem(E item) { + this.item = item; + } + + // TODO: do not copy & ++version + public void concat(ListCell _cell) { + ListCell cell = _cell.clone(); + ListCell lastButOne = this.previous.previous; + this.previous = cell.previous; + linkCells(lastButOne, cell); + } + + // ++version + public void reverse(ListCell nilCell) { + ListCell rightCell = nilCell.previous; + ListCell leftCell = this; + + while (leftCell != rightCell) { + E rightItem = rightCell.getItem(); + rightCell.setItem(leftCell.getItem()); + leftCell.setItem(rightItem); + + if(leftCell.next == rightCell) { + break; + } + + leftCell = leftCell.next; + rightCell = rightCell.previous; + } + } + + public ListCell clone() { + ListCell cell = this; + ListCell result = new ConsCell<>(cell.getItem()); + ListCell newCell = result; + cell = cell.getNext(); + + while (!cell.isEmpty()) { + ListCell newNextCell = new ConsCell<>(cell.getItem()); + linkCells(newCell, newNextCell); + + newCell = newNextCell; + cell = cell.getNext(); + } + + ListCell newNilCell = cell.clone(); + linkCells(newNilCell, result); + linkCells(newCell, newNilCell); + + return result; + } + + public ListCell map(Function mapper) { + ListCell cell = this; + ListCell result = new ConsCell<>(mapper.apply(cell.getItem())); + ListCell newCell = result; + cell = cell.getNext(); + + while (!cell.isEmpty()) { + ListCell newNextCell = new ConsCell<>(mapper.apply(cell.getItem())); + linkCells(newCell, newNextCell); + newCell = newNextCell; + cell = cell.getNext(); + } + + ListCell newNilCell = cell.map(mapper); + linkCells(newNilCell, result); + linkCells(newCell, newNilCell); + + return result; + } + + // ++version + public void applyMap(UnaryOperator mapper) { + ListCell cell = this; + cell.setItem(mapper.apply(cell.getItem())); + cell = cell.getNext(); + while (!cell.isEmpty()) { + cell.setItem(mapper.apply(cell.getItem())); + cell = cell.getNext(); + } + } + + public boolean isEqual(ListCell cell) { + if(cell.isEmpty()) + return false; + if (!this.getItem().equals(cell.getItem())) + return false; + + ListCell thisCell = this.getNext(); + cell = cell.getNext(); + while (!thisCell.isEmpty()) { + + if (cell.isEmpty()) + return false; + if(!thisCell.getItem().equals(cell.getItem())) + return false; + + thisCell = thisCell.getNext(); + cell = cell.getNext(); + } + return thisCell.isEqual(cell); + } + + // public boolean isEqual(List list) { + // if (list.isEmpty()) + // return false; + // if (!this.getItem().equals(list.head())) + // return false; + + // ListCell thisCell = this.getNext(); + // list = list.tail(); + // while (!thisCell.isEmpty()){ + + // if(list.isEmpty()) + // return false; + // if(!thisCell.getItem().equals(list.head())) + // return false; + + // thisCell = thisCell.getNext(); + // list = list.tail(); + // } + // return thisCell.isEqual(list); + // } + + public String toString(){ + String result = "[" + this.getItem(); + ListCell thisCell = this.getNext(); + String sep = ", "; + while (!thisCell.isEmpty()) { + result = result + sep + thisCell.getItem(); + thisCell = thisCell.getNext(); + } + return result + "]"; + } +} diff --git a/Immutable_collections_java8_project/src/collections/implementations/VersionedDoubleLinkedList.java b/Immutable_collections_java8_project/src/collections/implementations/VersionedDoubleLinkedList.java new file mode 100644 index 0000000..7859a02 --- /dev/null +++ b/Immutable_collections_java8_project/src/collections/implementations/VersionedDoubleLinkedList.java @@ -0,0 +1,124 @@ +package collections.implementations; + +import java.util.function.Function; +import java.util.function.UnaryOperator; + +// TODO: double pointer +public final class VersionedDoubleLinkedList { + + private ListCell firstCell; + private int version; + + public VersionedDoubleLinkedList() { + this(new NilCell(), 0); + } + + public VersionedDoubleLinkedList(ListCell newFirstCell, int version) { + this.version = version; + this.firstCell = newFirstCell; + } + + public ListCell getFirstCell(){ + return this.firstCell; + } + + public int getVersion() { + return this.version; + } + + private void checkVersion(int clientVersion) { + if (clientVersion == this.version) + return; + throw new UnsupportedOperationException("Version is outdated. Found: " + + clientVersion + + " - Expected: " + + this.version); + } + + public void addFirst(E head, ListCell cell, int clientVersion) { + this.checkVersion(clientVersion); + if (cell.isFirst()) { + this.firstCell = new ConsCell(head, cell); + } else { + this.version++; + cell.getPrevious().setItem(head); + } + } + + public ListCell tail(ListCell thisCell, int thisVersion) { + this.checkVersion(thisVersion); + return thisCell.getNext(); + } + + public E head(ListCell thisCell, int thisVersion) { + this.checkVersion(thisVersion); + return thisCell.getItem(); + } + + public ListCell concatenate(ListCell thisCell, + int thisVersion, + VersionedDoubleLinkedList other, + ListCell otherCell, + int otherVersion) { + this.checkVersion(thisVersion); + other.checkVersion(otherVersion); + + if (otherCell.isEmpty()) + return thisCell; + + if (thisCell.isEmpty()) { + this.version++; + this.firstCell = otherCell.clone(); // TODO: do not copy + return this.firstCell; + } else { + this.version++; + this.firstCell.concat(otherCell); + return thisCell; + } + } + + public void reverse(ListCell thisCell, int thisVersion) { + this.checkVersion(thisVersion); + this.version++; + thisCell.reverse(firstCell.previous); + } + + public boolean isEmpty(ListCell cell, int thisVersion) { + this.checkVersion(thisVersion); + return cell.isEmpty(); + } + + public VersionedDoubleLinkedList map(ListCell thisCell, int thisVersion, Function mapper) { + this.checkVersion(thisVersion); + ListCell newCell = thisCell.map(mapper); + return new VersionedDoubleLinkedList(newCell, 0); + } + + public void applyMap(ListCell thisCell, int thisVersion, UnaryOperator op) { + this.checkVersion(thisVersion); + this.version++; + thisCell.applyMap(op); + } + + public boolean isEqual(ListCell thisCell, + int thisVersion, + VersionedDoubleLinkedList that, + ListCell otherCell, + int otherVersion) { + + this.checkVersion(thisVersion); + that.checkVersion(otherVersion); + + return thisCell.isEqual(otherCell); + } + + // public boolean isEqual(ListCell thisCell, int thisVersion, List thatList){ + // this.checkVersion(thisVersion); + // return thisCell.isEqual(thatList); + // } + + public String toString(ListCell thisCell, int thisVersion) { + this.checkVersion(thisVersion); + return thisCell.toString(); + } +} diff --git a/Immutable_collections_java8_project/src/collections/interfaces/ImmutableCoreList.java b/Immutable_collections_java8_project/src/collections/interfaces/ImmutableCoreList.java new file mode 100644 index 0000000..2c06f5d --- /dev/null +++ b/Immutable_collections_java8_project/src/collections/interfaces/ImmutableCoreList.java @@ -0,0 +1,366 @@ +package collections.interfaces; + +// http://www.scala-lang.org/api/2.11.0/index.html#scala.collection.immutable.List +// http://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true +// http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/ImmutableList.html + +import java.util.Arrays; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.ArrayList; +import java.util.Optional; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +public interface ImmutableCoreList extends Iterable, +Cloneable { + + public ImmutableCoreList create(E[] elems); + public ImmutableCoreList create(Collection elems); + + /** + * Returns true if this list contains no elements. + * + * @returns true if this list contains no elements + */ + boolean isEmpty(); + + /** + * Sorts this list using the supplied Comparator to compare elements. + * @param comparator + * @return the list + */ + default ImmutableCoreList sort(Comparator comparator) { + E[] a = (E[]) toArray(); + Arrays.sort(a, comparator); + return create(a); + } + + /** + * Returns whether given predicate is satisfied by at least one element + * of the list. + * + * @param predicate The predicate to be tested on elements of the list. + * @returns true if predicate is satisfied by at least one element of + * the list. + */ + default boolean any(Predicate predicate) { + for (E elem : this) + if (predicate.test(elem)) + return true; + return false; + } + + /** + * Returns whether given predicate is satisfied by all elements of the + * list. + * + * @param predicate The predicate to be tested on elements of the list. + * @returns true if predicate is satified by all elements of the list. + */ + default boolean all(Predicate predicate) { + for (E elem : this) + if (!predicate.test(elem)) + return false; + return true; + } + + /** + * Returns the first index where the element is located in the list, or -1. + * + * @param o the element to look for + * @return its position, or -1 if not found + */ + default int indexOf(E elem) { + int i = 0; + for (E other : this) + if (equals(elem, other)) + return i; + else + ++i; + return -1; + } + + /** + * Compare two objects according to Collection semantics. + * + * @param o1 the first object + * @param o2 the second object + * @return o1 == null ? o2 == null : o1.equals(o2) + */ + static boolean equals(Object o1, Object o2) { + return o1 == null ? o2 == null : o1.equals(o2); + } + + /** + * Returns true if this list contains the specified element. More formally, + * returns true if and only if this list contains at least one element e + * such that (o==null ? e==null : o.equals(e)). + * + * @param elem the element to look for + * @return true if it is found + */ + default boolean contains(E elem) { + return any((E other) -> equals(elem, other)); + } + + /** + * Returns true if this list contains all of the elements of the + * specified collection. + * + * @param elems the elements to look for + * @return true if this list contains all of the elements of the + * specified collection + */ + default boolean containsAll(Collection elems) { + return containsAll(create(elems)); + } + + /** + * Returns true if this list contains all of the elements of the + * specified list. + * + * @param elems the elements to look for + * @return true if this list contains all of the elements of the + * specified list + */ + default boolean containsAll(ImmutableCoreList elems) { + return elems.all((E elem) -> contains(elem)); + } + + /** + * Returns true if this list contains all of the given elements + * + * @param elems the elements to look for + * @return true if this list contains all of the given elements + */ + @SuppressWarnings({"unchecked"}) + default boolean containsAll(E... elems) { + return containsAll(create(elems)); + } + + /** + * Returns a new list consisting of the results of applying the given + * function to the elements of this list. + * + * @param mapper a function to apply to each element + * @returns the new list + */ + default ImmutableCoreList map(Function mapper) { + List elems = new ArrayList(); + for (E elem : this) { + elems.add(mapper.apply(elem)); + } + return create(elems); + } + + /** + * Returns a list consisting of the elements of this list that match the + * given predicate. + * + * @param predicate The predicate to be tested on elements of the list. + * @return a list consisting of the elements of this list that match the + * given predicate. + */ + default ImmutableCoreList filter(Predicate predicate) { + ArrayList list = new ArrayList(); + for (E elem : this) + if (predicate.test(elem)) + list.add(elem); + return create(list); + } + + /** + * Performs a reduction on the elements of this list, using an associative + * accumulation function, and returns an Optional describing the reduced + * value, if any. + * + * @param accumulator An associative function for combining two values + * @return an Optional describing the result of the reduction + * @throws NullPointerException - if the result of the reduction is null + */ + default Optional reduce(BinaryOperator accumulator) { + Iterator it = iterator(); + if (!it.hasNext()) + return Optional.empty(); + + E result = it.next(); + while (it.hasNext()) + result = accumulator.apply(result, it.next()); + return Optional.of(result); + } + + default Spliterator spliterator() { + return Spliterators.spliteratorUnknownSize(iterator(), + Spliterator.IMMUTABLE | + Spliterator.ORDERED); + } + + /** + * Returns a sequential Stream with this collection as its source. + * + * @return a sequential Stream over the elements in this collection + */ + default Stream stream() { + return StreamSupport.stream(spliterator(), false); + } + + /** + * Returns a parallel Stream with this collection as its source. + * + * @return a parallel Stream over the elements in this collection + */ + default Stream parallelStream() { + return StreamSupport.stream(spliterator(), true); + } + + /** + * Returns an array containing all of the elements in this list in + * proper sequence (from first to last element). + * + * The returned array will be "safe" in that no references to it are + * maintained by this list. (In other words, this method must allocate + * a new array). The caller is thus free to modify the returned array. + * + * This method acts as bridge between array-based and collection-based APIs. + * + * @return an array containing all of the elements in this list in + * proper sequence + */ + @SuppressWarnings("unchecked") + default E[] toArray() { //TODO unused E elem + int size = 0; + for ( @SuppressWarnings("unused") E elem : this) + ++size; + return toArray((E[]) new Object[size]); + } + + /** + * Returns an array containing all of the elements in this list in + * proper sequence (from first to last element); the runtime type of the + * returned array is that of the specified array. If the list fits in + * the specified array, it is returned therein. Otherwise, a new array + * is allocated with the runtime type of the specified array and the + * size of this list. + * + * If the list fits in the specified array with room to spare (i.e., the + * array has more elements than the list), the element in the array + * immediately following the end of the list is set to null. (This is + * useful in determining the length of the list only if the caller knows + * that the list does not contain any null elements.) + * + * Like the toArray() method, this method acts as bridge between array- + * based and collection-based APIs. Further, this method allows precise + * control over the runtime type of the output array, and may, under + * certain circumstances, be used to save allocation costs. + * + * Suppose x is a list known to contain only strings. The following code + * can be used to dump the list into a newly allocated array of String: + * String[] y = x.toArray(new String[0]); + * + * Note that toArray(new Object[0]) is identical in function to toArray(). + * + * @param a -the array into which the elements of the list are to be + * stored, if it is big enough; otherwise, a new array of the same + * runtime type is allocated for this purpose. + * @return an array containing the elements of the list + */ + + default E[] toArray(E[] a) { + int i = 0; + for (E elem : this) { + a[i] = elem; + ++i; + } + return a; + } + + /** + * Returns a list containing all of the elements in this list in proper + * sequence. + * + * @return a list containing all of the elements in this list in proper + * sequence + */ + default List asList() { + List myList = new ArrayList(); + for (E e : this){ + myList.add(e); + } + return myList; + } + + public ImmutableCoreList clone(); + + // To be used for the clone() method in concrete classes (since Object + // methods cannot be overriden with the default keyword) + static ImmutableCoreList clone(ImmutableCoreList list) { + return list.create(list.asList()); + } + + /** + * Compares the specified object with this list for equality. Returns true + * if and only if the specified object is also a list, both lists have the + * same size, and all corresponding pairs of elements in the two lists are + * equal. (Two elements e1 and e2 are equal if + * (e1==null ? e2==null : e1.equals(e2)).) In other words, two + * lists are defined to be equal if they contain the same elements in the + * same order. This definition ensures that the equals method works properly + * across different implementations of the ImmutableList interface. + * + * @param o the object to be compared for equality with this list + * @return if the specified object is equal to this list + */ + boolean equals(Object o); + + // To be used for the equals() method in concrete classes (since Object + // methods cannot be overriden with the default keyword) + static boolean equals(ImmutableCoreList list, Object o) { + if (! (o instanceof ImmutableCoreList)) + return false; + + @SuppressWarnings("rawtypes") + ImmutableCoreList other = (ImmutableCoreList) o; + + Iterator it1 = list.iterator(); + @SuppressWarnings("rawtypes") Iterator it2 = other.iterator(); + + while (it1.hasNext() && it2.hasNext()) { + if (!equals(it1.next(), it2.next())) + return false; + } + if (it1.hasNext() || it2.hasNext()) + return false; + + return true; + } + + /** + * Hash an object. + * + * @param o the object to hash + * @return o1 == null ? 0 : o1.hashCode() + */ + static int hashCode(Object o) { + return o == null ? 0 : o.hashCode(); + } + + public int hashCode(); + + // To be used for the hashCode() method in concrete classes (since Object + // methods cannot be overriden with the default keyword) + static int hashCode(ImmutableCoreList list) { + int hashCode = 1; + Iterator itr = list.iterator(); + while (itr.hasNext()) + hashCode = 31 * hashCode + hashCode(itr.next()); + return hashCode; + } +} diff --git a/Immutable_collections_java8_project/src/collections/interfaces/ImmutableList.java b/Immutable_collections_java8_project/src/collections/interfaces/ImmutableList.java index b2527d1..2b6075d 100644 --- a/Immutable_collections_java8_project/src/collections/interfaces/ImmutableList.java +++ b/Immutable_collections_java8_project/src/collections/interfaces/ImmutableList.java @@ -1,45 +1,13 @@ package collections.interfaces; -// http://www.scala-lang.org/api/2.11.0/index.html#scala.collection.immutable.List -// http://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true -// http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/ImmutableList.html - -import java.util.Arrays; import java.util.Collection; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; -import java.util.Optional; -import java.util.Spliterator; -import java.util.Spliterators; -import java.util.function.BinaryOperator; import java.util.function.Function; import java.util.function.Predicate; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; - -public interface ImmutableList extends InductiveList, - IterativeList, - Iterable, - Cloneable { +import java.util.NoSuchElementException; - ImmutableList create(E[] elems); +public interface ImmutableList extends InductiveList, IterativeList { - /** - * Returns true if this list contains no elements. - * - * @returns true if this list contains no elements - */ - default boolean isEmpty() { - return size() == 0; - } - - /** - * Returns the number of elements in this list. - * - * @returns the number of elements in this list - **/ - int size(); + public ImmutableList create(E[] elems); /** * Returns a portion of this list. @@ -53,46 +21,21 @@ default boolean isEmpty() { * order (fromIndex > toIndex) */ ImmutableList subList(int fromIndex, int toIndex) throws - IndexOutOfBoundsException, - IllegalArgumentException; // Java && Guava + IndexOutOfBoundsException, + IllegalArgumentException; /** * Returns a new list with the elements of this list in reverse order. * * @return a new list with the elements of this list in reverse order. */ - ImmutableList reverse(); // Guava: reverse - - /** - * Sorts this list using the supplied Comparator to compare elements. - * @param comparator - * @return the list - */ - default ImmutableList sort(Comparator comparator) { // Java: sort, Scala: sorted/sortWith - E[] a = toArray(); - Arrays.sort(a, comparator); - return create(a); + default ImmutableList reverse() { + if (isEmpty()) + return this; + else + return tail().reverse().concat(head()); } - /** - * Returns whether given predicate is satisfied by at least one element - * of the list. - * - * @param predicate The predicate to be tested on elements of the list. - * @returns true if predicate is satisfied by at least one element of - * the list. - */ - boolean any(Predicate predicate); // Scala: exists/find - - /** - * Returns whether given predicate is satisfied by all elements of the - * list. - * - * @param predicate The predicate to be tested on elements of the list. - * @returns true if predicate is satified by all elements of the list. - */ - boolean all(Predicate predicate); // Scala: forall - /** * Returns a new list containing the elements from this list followed by * the elements from the given list. @@ -101,7 +44,13 @@ default ImmutableList sort(Comparator comparator) { // Java: sort, * @returns a new list containing the elements from this list followed * by the elements from the given list */ - ImmutableList concat(Collection elems); + default ImmutableList concat(Collection elems) { + ImmutableList list = this; + for (E elem : elems){ + list = list.concat(elem); + } + return list; + } /** * Returns a new list containing the elements from this list followed by @@ -111,7 +60,13 @@ default ImmutableList sort(Comparator comparator) { // Java: sort, * @returns a new list containing the elements from this list followed * by the elements from the given list */ - ImmutableList concat(ImmutableList elems); + default ImmutableList concat(ImmutableList elems) { + ImmutableList list = this; + for (E elem : elems){ + list = list.concat(elem); + } + return list; + } /** * Returns a new list containing the elements from this list followed by @@ -122,7 +77,13 @@ default ImmutableList sort(Comparator comparator) { // Java: sort, * by the elements from the given list */ @SuppressWarnings({"unchecked"}) - ImmutableList concat(E... elems); + default ImmutableList concat(E... elems) { + ImmutableList list = this; + for (int i = 0 ; i sort(Comparator comparator) { // Java: sort, * @returns a new list containing the elements from this list followed * by the elements from the given list */ - ImmutableList concat(E elem); + default ImmutableList concat(E elem) { + @SuppressWarnings("unchecked") + E[] elems = (E[]) new Object[size() + 1]; + int i = 0; + for (E e : this) { + elems[i] = e; + ++i; + } + elems[size()] = elem; + return create(elems); + } /** * Returns a new list without all the elements of the specified @@ -142,7 +113,13 @@ default ImmutableList sort(Comparator comparator) { // Java: sort, * @return a new list without all the elements of the specified * elements from this list */ - ImmutableList remove(ImmutableList elems); + default ImmutableList remove(ImmutableList elems) { + ImmutableList list = this; + for (E elem : elems) { + list = list.remove(elem); + } + return list; + } /** * Returns a new list without all the elements of the specified @@ -152,7 +129,13 @@ default ImmutableList sort(Comparator comparator) { // Java: sort, * @return a new list without all the elements of the specified * elements from this list */ - ImmutableList remove(Collection elems); + default ImmutableList remove(Collection elems) { + ImmutableList list = this; + for (E elem : elems) { + list = list.remove(elem); + } + return list; + } /** * Returns a new list without all the element of the specified elements @@ -163,7 +146,13 @@ default ImmutableList sort(Comparator comparator) { // Java: sort, * from this list */ @SuppressWarnings({"unchecked"}) - ImmutableList remove(E... elems); + default ImmutableList remove(E... elems) { + ImmutableList list = this; + for (int i = 0 ; i sort(Comparator comparator) { // Java: sort, * @return a new list without the first occurrence of the specified * element from this list */ - ImmutableList remove(E elem) throws IllegalArgumentException; + @SuppressWarnings("unchecked") + default ImmutableList remove(E elem) throws IllegalArgumentException { + E[] newElems; + int i; + boolean remove; + newElems = (E[]) new Object[size() - 1]; + i = 0; + remove = false; + for (E e : this) { + if(!remove && ImmutableCoreList.equals(elem, e)) + remove = true; + else{ + if (i == this.size()-1) + throw new IllegalArgumentException(); + newElems[i] = e; + i++; + } + } + + return create(newElems); + } /** * Returns a new list without the element at the specified position in @@ -185,173 +194,42 @@ default ImmutableList sort(Comparator comparator) { // Java: sort, */ ImmutableList remove(int index) throws ArrayIndexOutOfBoundsException; - /** - * Returns true if this list contains the specified element. More formally, - * returns true if and only if this list contains at least one element e - * such that (o==null ? e==null : o.equals(e)). - * - * @param elem the element to look for - * @return true if it is found - */ - boolean contains(E elem); // Scala, Java, Guava - - /** - * Returns true if this list contains all of the elements of the - * specified collection. - * - * @param elems the elements to look for - * @return true if this list contains all of the elements of the - * specified collection - */ - boolean containsAll(Collection elems); - - /** - * Returns true if this list contains all of the elements of the - * specified list. - * - * @param elems the elements to look for - * @return true if this list contains all of the elements of the - * specified list - */ - boolean containsAll(ImmutableList elems); - - /** - * Returns true if this list contains all of the given elements - * - * @param elems the elements to look for - * @return true if this list contains all of the given elements - */ - @SuppressWarnings({"unchecked"}) - boolean containsAll(E... elems); - - /** - * Returns a new list consisting of the results of applying the given - * function to the elements of this list. - * - * @param mapper a function to apply to each element - * @returns the new list - */ - ImmutableList map(Function mapper); // Scala: map + // To be used for the clone() method in concrete classes (since Object + // methods cannot be overriden with the default keyword) + static ImmutableList clone(ImmutableList list) { + return list.subList(0, list.size()); + } - /** - * Returns a list consisting of the elements of this list that match the - * given predicate. - * - * @param predicate The predicate to be tested on elements of the list. - * @return a list consisting of the elements of this list that match the - * given predicate. - */ - ImmutableList filter(Predicate predicate); // Scala: filter + default ImmutableList tail() throws UnsupportedOperationException { + if (isEmpty()) + throw new UnsupportedOperationException(); + else + return subList(1, size()); + } - /** - * Performs a reduction on the elements of this list, using an associative - * accumulation function, and returns an Optional describing the reduced - * value, if any. - * - * @param accumulator An associative function for combining two values - * @return an Optional describing the result of the reduction - * @throws NullPointerException - if the result of the reduction is null - */ - Optional reduce(BinaryOperator accumulator); // Scala: reduce - default Spliterator spliterator() { - return Spliterators.spliterator(iterator(), - size(), - Spliterator.IMMUTABLE | - Spliterator.ORDERED | - Spliterator.SIZED | - Spliterator.SUBSIZED); + default E head() throws NoSuchElementException { + if (isEmpty()) + throw new NoSuchElementException(); + else + return get(0); } - /** - * Returns a sequential Stream with this collection as its source. - * - * @return a sequential Stream over the elements in this collection - */ - default Stream stream() { - return StreamSupport.stream(spliterator(), false); + default E last() throws NoSuchElementException { + if (isEmpty()) + throw new NoSuchElementException(); + else + return get(size()-1); } - /** - * Returns a parallel Stream with this collection as its source. - * - * @return a parallel Stream over the elements in this collection - */ - default Stream parallelStream() { - return StreamSupport.stream(spliterator(), true); + @SuppressWarnings("unchecked") + default ImmutableList map(Function mapper) { + return (ImmutableList) InductiveList.super.map(mapper); } - /** - * Compares the specified object with this list for equality. Returns true - * if and only if the specified object is also a list, both lists have the - * same size, and all corresponding pairs of elements in the two lists are - * equal. (Two elements e1 and e2 are equal if - * (e1==null ? e2==null : e1.equals(e2)).) In other words, two - * lists are defined to be equal if they contain the same elements in the - * same order. This definition ensures that the equals method works properly - * across different implementations of the ImmutableList interface. - * - * @param o the object to be compared for equality with this list - * @return if the specified object is equal to this list - */ - boolean equals(Object o); - - /** - * Returns an array containing all of the elements in this list in - * proper sequence (from first to last element). - * - * The returned array will be "safe" in that no references to it are - * maintained by this list. (In other words, this method must allocate - * a new array). The caller is thus free to modify the returned array. - * - * This method acts as bridge between array-based and collection-based APIs. - * - * @return an array containing all of the elements in this list in - * proper sequence - */ - E[] toArray(); // Scala && Java: toArray - - /** - * Returns an array containing all of the elements in this list in - * proper sequence (from first to last element); the runtime type of the - * returned array is that of the specified array. If the list fits in - * the specified array, it is returned therein. Otherwise, a new array - * is allocated with the runtime type of the specified array and the - * size of this list. - * - * If the list fits in the specified array with room to spare (i.e., the - * array has more elements than the list), the element in the array - * immediately following the end of the list is set to null. (This is - * useful in determining the length of the list only if the caller knows - * that the list does not contain any null elements.) - * - * Like the toArray() method, this method acts as bridge between array- - * based and collection-based APIs. Further, this method allows precise - * control over the runtime type of the output array, and may, under - * certain circumstances, be used to save allocation costs. - * - * Suppose x is a list known to contain only strings. The following code - * can be used to dump the list into a newly allocated array of String: - * String[] y = x.toArray(new String[0]); - * - * Note that toArray(new Object[0]) is identical in function to toArray(). - * - * @param a -the array into which the elements of the list are to be - * stored, if it is big enough; otherwise, a new array of the same - * runtime type is allocated for this purpose. - * @return an array containing the elements of the list - */ - E[] toArray(E[] a); - - /** - * Returns a list containing all of the elements in this list in proper - * sequence. - * - * @return a list containing all of the elements in this list in proper - * sequence - */ - List asList(); // Scala: toList, Guava: asList - - ImmutableList clone(); + default ImmutableList filter(Predicate predicate) { + return (ImmutableList) InductiveList.super.filter(predicate); + } + ImmutableList cons(E elem); } diff --git a/Immutable_collections_java8_project/src/collections/interfaces/InductiveList.java b/Immutable_collections_java8_project/src/collections/interfaces/InductiveList.java index ab7712e..3e0a155 100644 --- a/Immutable_collections_java8_project/src/collections/interfaces/InductiveList.java +++ b/Immutable_collections_java8_project/src/collections/interfaces/InductiveList.java @@ -1,8 +1,10 @@ package collections.interfaces; +import java.util.function.Function; +import java.util.function.Predicate; import java.util.NoSuchElementException; -public interface InductiveList { +public interface InductiveList extends ImmutableCoreList { //TODO ERROR : No isEmpty() method. /** * Return a new list with the elements of this list appended to given element. @@ -10,7 +12,7 @@ public interface InductiveList { * @param elem The first element of the new list * @return a new list with the elements of this list appended to given element. */ - ImmutableList cons(E elem); // Scala: + operator + InductiveList cons(E elem); /** * Returns the first element in the list. @@ -26,7 +28,7 @@ public interface InductiveList { * @returns a list with all elements of this list except the first one * @throws UnsupportedOperationException if this list is empty */ - ImmutableList tail() throws UnsupportedOperationException; + InductiveList tail() throws UnsupportedOperationException; /** * Returns the last element of the list. @@ -35,4 +37,13 @@ public interface InductiveList { * @throws NoSuchElementException if the list is empty */ E last() throws NoSuchElementException; + + @SuppressWarnings("unchecked") + default InductiveList map(Function mapper) { + return (InductiveList) ImmutableCoreList.super.map(mapper); + } + + default InductiveList filter(Predicate predicate) { + return (InductiveList) ImmutableCoreList.super.filter(predicate); + } } diff --git a/Immutable_collections_java8_project/src/collections/interfaces/IterativeList.java b/Immutable_collections_java8_project/src/collections/interfaces/IterativeList.java index cfd29cf..b8ba2c1 100644 --- a/Immutable_collections_java8_project/src/collections/interfaces/IterativeList.java +++ b/Immutable_collections_java8_project/src/collections/interfaces/IterativeList.java @@ -1,6 +1,23 @@ package collections.interfaces; -public interface IterativeList { +import java.util.Spliterators; +import java.util.Spliterator; +import java.util.Iterator; +import java.util.function.Function; +import java.util.function.Predicate; + +public interface IterativeList extends ImmutableCoreList { + + default boolean isEmpty() { + return size() == 0; + } + + /** + * Returns the number of elements in this list. + * + * @returns the number of elements in this list + **/ + int size(); /** * Returns the element at the specified position in this list. @@ -10,12 +27,56 @@ public interface IterativeList { */ E get(int index) throws IndexOutOfBoundsException; - /** - * Returns the first index where the element is located in the list, or -1. - * - * @param o the element to look for - * @return its position, or -1 if not found - */ - int indexOf(E elem); + default Spliterator spliterator() { + return Spliterators.spliterator(iterator(), + size(), + Spliterator.IMMUTABLE | + Spliterator.ORDERED | + Spliterator.SIZED | + Spliterator.SUBSIZED); + } + + public boolean equals(Object o); + + // To be used for the equals() method in concrete classes (since Object + // methods cannot be overridden with the default keyword) + @SuppressWarnings("unchecked") + static boolean equals(IterativeList list, Object o) { + if (o instanceof IterativeList) + return list.equals((IterativeList)o); + else if (o instanceof ImmutableCoreList) + return ImmutableCoreList.equals(list, o); + else + return false; + } + + default public boolean equals(IterativeList other) { + if (size() != other.size()) + return false; + + Iterator it1 = iterator(); + @SuppressWarnings("rawtypes") + Iterator it2 = other.iterator(); + + while (it1.hasNext()) { + if (!ImmutableCoreList.equals(it1.next(), it2.next())) //TODO + return false; + } + + return true; + } + + @SuppressWarnings({ "unchecked"}) + default E[] toArray() { + return toArray((E[]) new Object[size()]); + } + + @SuppressWarnings("unchecked") + default IterativeList map(Function mapper) { + return (IterativeList) ImmutableCoreList.super.map(mapper); + } + default IterativeList filter(Predicate predicate) { + return (IterativeList) ImmutableCoreList.super.filter(predicate); + } } diff --git a/Immutable_collections_java8_project/src/main/Benchmarks.java b/Immutable_collections_java8_project/src/main/Benchmarks.java index 8ffbf25..73142ea 100644 --- a/Immutable_collections_java8_project/src/main/Benchmarks.java +++ b/Immutable_collections_java8_project/src/main/Benchmarks.java @@ -79,9 +79,9 @@ public void runHalfImmuLinkedListBench(int warmup, int maxIterations) } - - - + + + private void execAll(ImmutableList list, int warmup, int maxIterations) { long execTime = 0; @@ -117,10 +117,10 @@ private void execAll(List list, int warmup, int maxIterations) } - - - - + + + + private long execGet(ImmutableList list, int warmup, int maxIterations) { long beg = 0; @@ -279,18 +279,18 @@ private long execConcat(List list, int warmup, int maxIterations) long beg = 0; long end = 0; long execTime = 0; - - for(int i=0; i < warmup; ++i) - { - beg = System.currentTimeMillis(); - for(int ite=0; ite < maxIterations; ++ite) - { - list.addAll((Collection) this.dummy); - } - end = System.currentTimeMillis(); - execTime += (end-beg); - list.removeAll(this.dummy); - } + + for(int i=0; i < warmup; ++i) + { + beg = System.currentTimeMillis(); + for(int ite=0; ite < maxIterations; ++ite) + { + list.addAll((Collection) this.dummy); + } + end = System.currentTimeMillis(); + execTime += (end-beg); + list.removeAll(this.dummy); + } return (execTime/warmup); } } diff --git a/Immutable_collections_java8_project/src/main/Main.java b/Immutable_collections_java8_project/src/main/Main.java index bc10585..4e8c432 100644 --- a/Immutable_collections_java8_project/src/main/Main.java +++ b/Immutable_collections_java8_project/src/main/Main.java @@ -5,7 +5,7 @@ public class Main { public static void main(String[] args) { System.out.println("Main."); Benchmarks bench = new Benchmarks(100); - bench.run(10, 10000); + bench.run(10, 1000); } } diff --git a/Immutable_collections_java8_project/src/test/AllTests.java b/Immutable_collections_java8_project/src/test/AllTests.java index c0cd562..dc76549 100644 --- a/Immutable_collections_java8_project/src/test/AllTests.java +++ b/Immutable_collections_java8_project/src/test/AllTests.java @@ -5,7 +5,12 @@ import org.junit.runners.Suite.SuiteClasses; @RunWith(Suite.class) -@SuiteClasses({ ImmutableArrayListTest.class, ImmutableLinkedListTest.class }) +@SuiteClasses({ + ImmutableArrayListTest.class, + ImmutableLinkedListTest.class, + ImmutableReversedArrayListTest.class, + DoubleLinkedListProxyTest.class + }) public class AllTests { } diff --git a/Immutable_collections_java8_project/src/test/DoubleLinkedListProxyTest.java b/Immutable_collections_java8_project/src/test/DoubleLinkedListProxyTest.java new file mode 100644 index 0000000..07752a6 --- /dev/null +++ b/Immutable_collections_java8_project/src/test/DoubleLinkedListProxyTest.java @@ -0,0 +1,122 @@ +package test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Before; +import org.junit.Test; + +import collections.implementations.DoubleLinkedListProxy; + +public class DoubleLinkedListProxyTest { + + DoubleLinkedListProxy list; + DoubleLinkedListProxy nil; + + @Before + public void setUp() { + list = new DoubleLinkedListProxy(); + nil = list.nil(); + } + + @Test + public void testNil() { + assertTrue(nil.isEmpty()); + } + + @Test + public void testIsEmpty() { + assertTrue(list.isEmpty()); + assertFalse(list.cons(1).isEmpty()); + } + + // @Test(expected=UnsupportedOperationException.class) + public void testTailException() { // TODO: should throw an exception + // nil.tail(); + assertEquals(nil, nil.tail()); + } + + @Test + public void testTail() { + list = list.cons(1); + list = list.cons(2); + assertEquals(nil.cons(1), list.tail()); + } + + @Test(expected=UnsupportedOperationException.class) + public void testHeadException() { + list.head(); + } + + @Test + public void testHead() { + list = list.cons(1).cons(2); + assertEquals(2, (int)list.head()); + } + + @Test + public void testCons() { + list = list.cons(3); + list = list.cons(2); + list = list.cons(1); + + assertEquals(1, (int)list.head()); list = list.tail(); + assertEquals(2, (int)list.head()); list = list.tail(); + assertEquals(3, (int)list.head()); + } + + @Test + public void testConcat() { + assertEquals(nil, list.concat(list)); + + DoubleLinkedListProxy expected = nil.cons(2).cons(1); + DoubleLinkedListProxy one = new DoubleLinkedListProxy().cons(1); + DoubleLinkedListProxy two = new DoubleLinkedListProxy().cons(2); + assertEquals(expected, one.concat(two)); + } + + @Test + public void testReverse() { + assertEquals(nil, list.reverse()); + + DoubleLinkedListProxy expected = new DoubleLinkedListProxy(); + expected = expected.cons(3).cons(2).cons(1); + + list = nil.cons(1).cons(2).cons(3); + assertEquals(expected, list.reverse()); + } + + @Test + public void testMap() { + list = list.cons(1).cons(2).cons(3); + + DoubleLinkedListProxy expected = new DoubleLinkedListProxy(); + expected = expected.cons(2).cons(4).cons(6); + + assertEquals(expected, list.map((Integer x) -> x * 2)); + } + + @Test + public void testEndoMap() { + list = list.cons(1).cons(2).cons(3); + + DoubleLinkedListProxy expected = new DoubleLinkedListProxy(); + expected = expected.cons(2).cons(4).cons(6); + + assertEquals(expected, list.endoMap((Integer x) -> x * 2)); + } + + @Test + public void testEquals() { + assertEquals(nil, list); + + list = list.cons(3).cons(2).cons(1); + DoubleLinkedListProxy expected = new DoubleLinkedListProxy(); + expected = expected.cons(3).cons(2); + assertFalse(expected.equals(list)); + + expected = expected.cons(1); + assertEquals(expected, list); + } +} diff --git a/Immutable_collections_java8_project/src/test/ImmutableArrayListTest.java b/Immutable_collections_java8_project/src/test/ImmutableArrayListTest.java index de65471..363a2fc 100644 --- a/Immutable_collections_java8_project/src/test/ImmutableArrayListTest.java +++ b/Immutable_collections_java8_project/src/test/ImmutableArrayListTest.java @@ -3,7 +3,7 @@ import org.junit.Before; -public class ImmutableArrayListTest extends ImmutableListTest { +public class ImmutableArrayListTest extends InductiveIterativeListTest { @Before public void setUp() { diff --git a/Immutable_collections_java8_project/src/test/ImmutableLinkedListTest.java b/Immutable_collections_java8_project/src/test/ImmutableLinkedListTest.java index eb8c020..56ba83a 100644 --- a/Immutable_collections_java8_project/src/test/ImmutableLinkedListTest.java +++ b/Immutable_collections_java8_project/src/test/ImmutableLinkedListTest.java @@ -1,26 +1,12 @@ package test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.stream.Stream; -import java.util.NoSuchElementException; -import java.util.Optional; - import org.junit.Before; -import org.junit.Test; -import collections.implementations.ImmutableLinkedList; -import collections.interfaces.ImmutableList; - -public class ImmutableLinkedListTest extends ImmutableListTest { +public class ImmutableLinkedListTest extends InductiveIterativeListTest { @Before public void setUp() { super.setUp(new ImmutableLinkedListFactory()); } + } diff --git a/Immutable_collections_java8_project/src/test/ImmutableReversedArrayListTest.java b/Immutable_collections_java8_project/src/test/ImmutableReversedArrayListTest.java new file mode 100644 index 0000000..3338adb --- /dev/null +++ b/Immutable_collections_java8_project/src/test/ImmutableReversedArrayListTest.java @@ -0,0 +1,13 @@ +package test; + +import org.junit.Before; + + +public class ImmutableReversedArrayListTest extends InductiveIterativeListTest { + + @Before + public void setUp() { + super.setUp(new ReversedArrayListFactory()); + } + +} diff --git a/Immutable_collections_java8_project/src/test/ImmutableListTest.java b/Immutable_collections_java8_project/src/test/InductiveIterativeListTest.java similarity index 87% rename from Immutable_collections_java8_project/src/test/ImmutableListTest.java rename to Immutable_collections_java8_project/src/test/InductiveIterativeListTest.java index 7a24cc8..7d9b942 100644 --- a/Immutable_collections_java8_project/src/test/ImmutableListTest.java +++ b/Immutable_collections_java8_project/src/test/InductiveIterativeListTest.java @@ -5,6 +5,8 @@ import static org.junit.Assert.assertTrue; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; @@ -43,7 +45,21 @@ public ImmutableList create() { } } -public abstract class ImmutableListTest { +class ReversedArrayListFactory implements ImmutableListFactory { + @SuppressWarnings("unchecked") + public ImmutableList create(E... _elems) { + List tmp = Arrays.asList(_elems); + Collections.reverse(tmp); + E[] elems = (E[]) tmp.toArray(); + + return new ImmutableArrayList(elems).reverse(); + } + public ImmutableList create() { + return new ImmutableArrayList().reverse(); + } +} + +public abstract class InductiveIterativeListTest { protected ImmutableList list; protected ImmutableList emptyList; @@ -191,6 +207,22 @@ public void IteratorExceptionTest2() { it.remove(); } + @Test + public void SubListIteratorTest() { + + // Test that iterators stop at the right last element for sublists + // (since they all share their structures with a superlist) + + ImmutableList subList = list.subList(1, list.size()-1); + assertEquals(1, subList.size()); + + int sizeWhenIterating = 0; + for (@SuppressWarnings("unused") Integer i : subList) + ++sizeWhenIterating; + + assertEquals(subList.size(), sizeWhenIterating); + } + @Test public void ContainsTest() { assertTrue(list.contains(1)); @@ -292,14 +324,18 @@ public void StreamTest() { @Test public void removeTest1() { - assertEquals(new ImmutableLinkedList(2, 3),list.remove(0)); - assertEquals(new ImmutableLinkedList(2, 3),list.remove(new Integer(1))); - assertEquals(new ImmutableLinkedList(3),list.remove(new Integer(1),new Integer(2))); - assertEquals(new ImmutableLinkedList(2),list.remove(new ImmutableLinkedList(1,3))); + Integer second = list.get(1); + Integer third = list.get(2); + + assertEquals(new ImmutableLinkedList(second, third),list.remove(0)); + + assertEquals(new ImmutableLinkedList(second, third),list.remove(new Integer(1))); + assertEquals(new ImmutableLinkedList(third),list.remove(new Integer(1), new Integer(2))); + assertEquals(new ImmutableLinkedList(second), list.remove(new ImmutableLinkedList(1,3))); List otherList = new ArrayList(); otherList.add(1); otherList.add(3); - assertEquals(new ImmutableLinkedList(2), list.remove(otherList)); + assertEquals(new ImmutableLinkedList(second), list.remove(otherList)); } @Test @@ -342,7 +378,7 @@ public void hashCodeTest() { @Test public void toarrayTest(){ Integer[] array= { 1 ,2 ,3 }; - Integer[] array2 = new Integer[array.length]; + Integer[] array2 = new Integer[array.length]; array2=list.toArray(array); //TODO before : array2=list.toArray(array2) -> Check validity assertEquals(array2[0],array[0]); assertEquals(array2[1],array[1]); @@ -350,7 +386,7 @@ public void toarrayTest(){ } @Test - public void asListTest(){ + public void asListTest() { List myList = new ArrayList(); List myList2 = new ArrayList(); myList.add(1); @@ -362,7 +398,7 @@ public void asListTest(){ } @Test - public void sortTest(){ + public void sortTest() { Comparator comp = (Integer x, Integer y) -> x.compareTo(y); assertEquals(list.sort(comp),list.reverse().sort(comp)); }