How to implement subList() in Custom ArrayList - java

I'm implementing my own generic ArrayList and everything is fine, but I've got a problem with the last method - List subList(int fromIndex, int toIndex). I've tried to implement it, but still, I only create a copy of my main list and modify only it. My current code is
public List<T> subList(int fromIndex, int toIndex) {
if (fromIndex < 0 || toIndex > size() || fromIndex > toIndex)
throw new IndexOutOfBoundsException();
Object subarray[] = new Object[toIndex - fromIndex];
for (int i = 0; i < subarray.length; i++) {
subarray[i] = array[fromIndex + i];
}
List<T> subList = Arrays.asList((T) subarray);
return subList;
}
I've also tried to do it using ArrayList instead of an array, but it still doesn't work (modify only my new subList instead of the whole list). How can I repair it? Do I have to implement another class?
EDIT
I also add my test method, I still get failure (the value in main list isn't changed)
#Test
void subListWithoutNulls() {
CustomArrayList<Integer> array = new CustomArrayList<>();
array.add(3);
array.add(7);
array.add(2);
array.add(5);
array.add(8);
array.add(3);
array.subList(1, 4).set(0, 12);
assertEquals(12, array.get(1));
}

If you derive from AbstractList, an implementation will be provided for you: https://docs.oracle.com/javase/7/docs/api/java/util/AbstractList.html#subList(int,%20int)
Otherwise you will have to write a new class that properly delegates everything to the original list.

Assuming you are doing this is a learning exercise, here's one way to create a sublist that has pass-through behaviour. It involves making an implementation of the List interface. Just about every method implementation is specifically to cater to the idea of a sublist. As the specs say, you don't have to consider the case of structural changes made to the underlying list (e.g. what if in between making a subList and e.g. calling size() on that subList, someone invokes .clear() on the top-level list? Does that mean the sublist should now return 0? You get to define what happens yourself, as per the spec of java.util.List.
public List<T> subList(int fromIndex, int toIndex) {
if (fromIndex < 0) throw new IndexOutOfBoundsException("fromIndex is below 0");
if (toIndex > size()) throw new IndexOutOfBoundsException("toIndex is above 'size'");
if (toIndex < fromIndex) throw new IndexOutOfBoundsException("toIndex is before fromIndex");
return new List<T>() {
public void size() {
return toIndex - fromIndex;
}
public void get(int idx) {
return MyList.this.get(idx + fromIndex);
}
public boolean add(T elem) {
return MyList.this.add(toIndex++, elem);
}
// and so on.
};
}
Take a look at that impl of the add method (which makes the assumption that the underlying add method always returns true - if your list impl doesn't, do not increment toIndex unless true is returned): It can be a tad complicated. Here, adding an item to the subList means the subList is now one larger than it was. For that matter, so is the underlying list. Also an add-to-the-end operation on a subList doesn't neccesarily mean that you're adding to the end of the underlying list, so you'd invoke the add-in-the-middle version. Outer.this.method() is java-ese for invoking a method from your outer class, which we need here, as both the inner class and the outer class have very similar methods, so we need to be clear when we invoke e.g. add(idx, elem) - is that invoking the subList's add method, or the underlying (outer class's) add method? Outer.this.x can be used to make that clear (if you don't do that, you get the inner list, and thus most likely a boatload of StackOverflowErrors if you try it).

Related

Implementing an Iterator for a Set, tracking the current element

How do you code an Iterator for a Set? Given that the iterator does not have access to the underlying data storage mechanism, and can only use the Set methods, is it possible to do this?
Every implementation I've managed to find creates the Iterator as an anonymous class; however, I am trying to figure out if there is a clever way to iterate over a Set while only accessing the methods provided by Set.
So far, the best I've managed to come up with looks like this:
import java.util.*;
public class SetIterator<E> implements Iterator
{
protected E[] arrayData;
protected Set<E> set;
protected int index;
protected boolean canRemove;
public SetIterator(Set<E> set)
{
this.set = set;
this.arrayData = (E[]) set.toArray();
this.index = -1;
this.canRemove = false;
}
public E next()
{
if(this.hasNext())
{
this.canRemove = true;
return this.arrayData[++this.index];
}
else
{
throw new NoSuchElementException("There is no next element");
}
}
public boolean hasNext()
{
return this.index + 1 < this.arrayData.length;
}
public void remove()
{
if(this.canRemove)
{
this.set.remove(this.arrayData[index--]);
this.arrayData = (E[]) this.set.toArray();
this.canRemove = false;
}
else
{
throw new IllegalStateException("Cannot remove element before calling next");
}
}
}
But that feels quite kludgy.... Is there a better way?
I think your title doesn't leave much space for answers, but if I use the following as your actual question:
How do you build an Iterator for a Set?
(and understand build as in get an instance of)
I think as PM 77-1 pointed out in the comments:
call the iterator() method on it, which it has since at least Java 1.5.
Keep in mind that it depends on the actual implementation of Set, wether the elements will always be iterated over in the same order.
if we look in AbstractCollection we will see that toArray actually calls the iterator() (abstract method) to produce the array which you will use, so your method still depends on the specific iterator, so you are essentially decorating the iterator.
public Object[] toArray() {
// Estimate size of array; be prepared to see more or fewer elements
Object[] r = new Object[size()];
Iterator<E> it = iterator();
for (int i = 0; i < r.length; i++) {
if (! it.hasNext()) // fewer elements than expected
return Arrays.copyOf(r, i);
r[i] = it.next();
}
return it.hasNext() ? finishToArray(r, it) : r;
}
Still not sure what you are trying to accomplish, the underlying datastructure of the set will have different (and specific) ways to efficently iterate the data, any generic solution would sacrafice performance, using the iterable interface should be generic enough.

I am trying to create a circular LinkedList Please tell me if its a correct way to do it

i have implemented logic like if i am giving a index that is not yet there then it will change the index to the reminder (Same like rotated i guess ).
import java.util.LinkedList;
public class MycircularlinkedList extends LinkedList {
private static int count = 0;
public Object get(int i) {
System.out.println("count==" + count);
if (i > count) {
i = i % count;
return super.get(i);
} else {
return super.get(i);
}
}
public boolean add(Object o) {
super.add(o);
count++;
return true;
}
public void add(int i, Object o) {
if (i > count)
i = i % count;
super.add(i, o);
count++;
}
}
A couple of points I can see:
count is static, this means you're only ever going to have one number here. Probably not what you want
count is redundant, use Collection#size()
The great thing about mod (%) is that it works for all numbers, you don't need to have the conditional. 2 % 12 == 14 % 12 == -10 % 12
If you're getting rid of the count property, you can get rid of your overridden #add(Object o) logic and just do return super.add(o);
I find some problem with your code: if count ==0 and if I use the method add(7,obj) ,then 7%0 will throw ArithmeticException.count should be declared to private since you may have two instances of your class.Also,you need to check
whether poll\offerLast method satisfies your needs,since you cant restrict
any client code to avoid using them.Finally,clone\readObject\writeObject
need to be overrried to include the count variable.
You're close.
(1) The term "circular linked list" is well-known to mean a list where the tail links back to the head (and vice versa if it's a doubly-linked list). Yours is more like a "circular buffer" stored in a linked list. We could call it LinkedListCircularBuffer or something.
(2) The class should be parameterized by the element type, thus
public class LinkedListCircularBuffer<E> extends LinkedList<E> {
#Override
public E get(int i) {
return super.get(i % size()); // simpler and faster without an "if"
}
}
(3) You can call size() instead of all the code to maintain another count.
(4) Your add(int i, Object o) method doesn't support the case where i == size(), but you can fix that by not overriding add() at all.
(5) Overridden methods need the #Override annotation.
(6) It's good style to always put braces around each "then" and "else" clause. Code like
if (i > count)
i = i % count;
is fragile, e.g. adding a println() statement into that "then" clause will break it.

fail fast iterator implementation

There are similar questions but not exactly what I want to ask.
I want to ask how Iterator checks for the modification.
This link says that its implementation is present in AbstractList class where an int variable modCount is defined that provides the number of times list size has been changed. This value is used in every next() call to check for any modifications in a function checkForComodification().
But I could not really understand it. If the value is checked only after every next call then if I do a remove followed by add in the same call, size won't change and modCount should not change as well. But removing and adding in the same loop iteration also throws exception.
If you look at the code for a Collection implementation, lets pick ArrayList; we have a modCount variable declared in AbstractList:
protected transient int modCount = 0;
And then in each and every modifying method (for example remove) for the ArrayList we have
public E remove(int index) {
rangeCheck(index);
modCount++;
//....
So the modCount is only ever incremented; it is never decremented.
In the Iterator we then have:
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
Where expectedModCount is a snapshot of the modCount taken at Iterator creation.
So if there is any modification to the underlying List while the same instance of an Iterator is in use then a ConcurrentModificationException will be thrown.
I suppose there is a corner case where if you carried out enough modifications then the int would overflow and return to it's original value again - this would be a rather large number or modifications however; 232 to be precise.
modCount always increases when the list is modified (hence mod count) so it should also increase when there's a removal.
Thus it would increase on both the remove and add call.
As Boris the Spider said there is the corner case that modCount overflows, you can see it by doing:
List<Integer> nums = new ArrayList<>();
for(int i = 0; i < 10; i++) nums.add(i);
for(int n : nums) {
System.out.println(n);
for(int i = -1; i < Integer.MAX_VALUE; i++) {
nums.add(i);
nums.remove(nums.size() - 1);
}
}
Which will (slowly) print 0 through 9 without throwing any exception.

Could anyone tell me why this returns an empty list (NPE)?

I have this code that is supposed to merge two instances of SortedLinkedList into one SLL (based on mergeSort merge), but is returning an empty list instead:
import java.util.LinkedList;
public class SortedLinkedList<T extends Comparable<? super T>>
extends LinkedList<T> {
private LinkedList<T> list; // the sorted list
// constructor, sorted with insertion sort
public SortedLinkedList(LinkedList<T> in)
{
if(in.peek() == null || in.size() == 1)
return;
else {
list = new LinkedList<T>();
for(T e : in)
list.add(e);
int i, j;
T temp;
for(i = 0; i < list.size(); i++){
j = i;
temp = list.get(j);
while(j > 0 && list.get(j-1).compareTo(temp) > 0){
list.set(j, list.get(j-1));
j--;
}
list.set(j, temp);
}
}
}
// return the union of the sorted linked lists this
// and other
public SortedLinkedList<T> makeUnion( SortedLinkedList<T> other)
{
list = new LinkedList<T>();
SortedLinkedList<T> temp = new SortedLinkedList<T>(list);
int i = 0, j = 0;
while(i < this.size() && j < other.size()){
if(this.get(i).compareTo(other.get(j)) <= 0){
temp.add(this.get(i));
i++;
}
else {
temp.add(other.get(j));
j++;
}
}
while(i < this.size()){
temp.add(this.get(i));
i++;
}
while(j < other.size()){
temp.add(other.get(j));
j++;
}
return temp;
}
// print the items in list
public void print()
{
for(T e : list)
System.out.println(e);
}
}
In the SLL constructor, I have it simply return on a null list (and the private variable, list, is initialized in the first line of this method). However from what I know, this should still give me an SLL object (initially also null). I can add to temp just fine in the method itself, but get a NullPointerException when printing the list.
I realize it's not very efficient to use get with LinkedList. I'll switch them with an iterator after I settle this.
Any hints would be quite appreciated.
EDIT: Interestingly, I get the same result if I put both lists in a temporary LL and then use the constructor on it. The types are compatible since SLL extends LL:
public SortedLinkedList<T> makeUnion( SortedLinkedList<T> other)
{
LinkedList<T> temp = new LinkedList<T>();
temp.addAll(this);
temp.addAll(other);
SortedLinkedList<T> merge = new SortedLinkedList(temp);
return merge;
}
EDIT2: It seems #Mead was correct... while size() and get() seem to work for the SLL, add() does not. I was thinking that since I'm extending LinkedList, it would work with the SLL as well. It didn't, and overriding them did nothing as well... I'm out of ideas for this. Suggestions?
Great! Your edit pretty much reveals your problem: you're not extending the LinkedList properly. Fix that, and then work on union.
The problem at hand: This is a class called SortedLinkedList. We can assume it's meant to be just like LinkedList, but the values in it are sorted. So, given that, this should work:
LinkedList<Integer> unsorted = new LinkedList<Integer>();
unsorted.add(200);
unsorted.add(100);
unsorted.add(300);
SortedLinkedList<Integer> sorted = new SortedLinkedList<Integer>(unsorted);
System.out.println(sorted.size());
for (Integer i : sorted) {
System.out.println(i);
}
// Should print out:
// 3
// 100
// 200
// 300
But it will not. Run your code, what does it print out?
Back? Why did it print out that? First, consider two variables you can use in the class's code: this refers to the SortedLinkedList object, and this.list refers to an instance variable inside that SortedLinkedList object. Then let's look at the constructor: when you add to the list, you're calling this.list.add(). What you have written makes SortedLinkedList a wrapper around the list instance variable - you're not adding to the SortedLinkedList (this) you are adding to a list inside that (this.list).
The only methods that use your this.list instance variable are the constructor, print, and makeUnion. All the other LinkedList methods aren't aware of the list variable, so when I call get():
LinkedList<Integer> unsorted = new LinkedList<Integer>();
unsorted.add(200);
unsorted.add(100);
unsorted.add(300);
SortedLinkedList<Integer> sorted = new SortedLinked<Integer>(unsorted);
System.out.println(sorted.get(0));
It doesn't know to look in your this.list variable, so it won't get 100 to print. In fact, it will crash because there is no value in index 0. You didn't add to the instance variables that get() actually uses, so the methods think that SortedLinkedList object is empty. this.list is a new variable that the inheritted methods don't know about.
So, if we examine your latest edit:
public SortedLinkedList<T> makeUnion( SortedLinkedList<T> other)
{
LinkedList<T> temp = new LinkedList<T>();
temp.addAll(this);
temp.addAll(other);
SortedLinkedList<T> merge = new SortedLinkedList(temp);
return merge;
}
temp.addAll(this) doesn't work, because all the methods of this think that the list is empty because they're not looking at this.list. temp.addAll(other) doesn't work either, for the same reason.
What is common when you extend classes is that you want the existing methods to continue working. This means that you need to store the data where get() and other methods expect it to be. How do you do that? Well, you're already doing it! You are already doing the right thing - but you are doing it on the instance variable this.list instead of this. Start calling this.add(), this.set(), this.size() instead of this.list.add() and remove the instance variable list completely - it's not needed, you have this. Then the data will be where the other methods expect it to be.
(And call super() on the first line of your constructor, so the code in the super class's constructor is called). Good luck on your homework - I'd recommend testing the object works as-is before adding new methods.
just curious after looking at the implementation, but couldn't you have just done a .addAll(...) followed by a Collections.sort(...)? That's what I would have preferred personally.

question on java list remove

The method public boolean remove(Object o) of List removes an object from list but does not shift the elements following.Just nulls the object value.
IMHO this is an uninintuitive design choice since the size of the list before and after removal remains the same.
Is there an elegant way to get a list with the elements shifted?
Thanks
No, that's not what it does. The element is removed and all indices following it are reduced by one. What makes you think it acts differently?
According to the Java API here it sais that the remove function of List DOES shift
Removes the element at the specified position in this list (optional operation). Shifts any subsequent elements to the left (subtracts one from their indices). Returns the element that was removed from the list.
EDIT:
Main class:
import java.util.ArrayList;
import java.util.Iterator;
public class Main {
public static void main(String[] args) {
ArrayList<A> x = new ArrayList<A>();
A one = new A("one");
A two = new A("two");
A three = new A("three");
A four = new A("four");
A five = new A("five");
A six = new A("six");
A seven = new A("seven");
A eight = new A("eight");
A nine = new A("nine");
A ten = new A("ten");
x.add(one);
x.add(two);
x.add(three);
x.add(four);
x.add(five);
x.add(six);
x.add(seven);
x.add(eight);
x.add(nine);
x.add(ten);
for(A item:x){
System.out.println(item.getStr());
}
x.remove(four);
Iterator<A> i = x.iterator();
while(i.hasNext()){
A item = i.next();
System.out.println(item.getStr());
}
}
}
The A Class:
public class A {
private String str;
public A(String x){
this.str = x;
}
public String getStr(){
return this.str;
}
}
works perfectly! no null pointer exception.
This is how it should be done. the first For loop is the alternative syntax for what i did wit the Iterator object. Actually Java automatically translates the first for loop in something that looks like the while loop.
If you look at ArrayList remove implementation, it uses a local method fastRemove(index) as follows:-
/*
* Private remove method that skips bounds checking and does not
* return the value removed.
*/
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
}
It does use arraycopy which is a proof that you get whole new list of fresh objects and not the null filled in between. Is this a proof?
The contract for java.util.List implies that calling remove will cause the size() to be decremented. If you're talking specifically about java.util.ArrayList then you might be right about the internal array not shifting its elements, but this is an implementation detail that shouldn't matter to you in 99% of all cases. If it still does matter, then you're trying to optimize for a specific situation and you should probably implement your own List or use something like java.util.LinkedList.
Either your observation is wrong or you are using some other kind of List implementation (and not ArrayList) that doesn't shift the elements to the right of the element being removed. Can you post your code?
If you look at the java.util.ArrayList source code in JDK8, you will see that the remove(Object o) method effectively copies the elements to the right of the element being removed, to the same array starting from the index of the element being removed. Look at the ArrayList source code for more info:
If all you need is an array of the data, then just call toArray().

Categories