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.
Related
The problem to solve is to find a non-repeating integer in an Integer list. I used a while loop to compare each value with another. The function, however, returns the wrong value. This is a Hackerrank challenge which can be found here .
public static int lonelyinteger(List<Integer> a) {
int lonelyInt = 0;
for (int i = 0; i < a.size(); i++) {
for (int j=1;j<a.size();j++){
while (a.get(i)!=a.get(j)){
lonelyInt+=a.get(i);
}
}
}
return lonelyInt;
}
I would really appreciate any hints and/or more straightforward solutions. I am new to Java and practicing my skills.
Your approach of comparing each number with all the other numbers is correct in principle.
If we compare the ith element of the array with all the other elements, and none are equal to it, then we know it is the unique number.
Your program is not doing this correctly.
Think of the loops like this:
The outer loop using the index i is giving us the number we are checking for loneliness, a.get(i).
The inner loop using the index j is giving us each number to check against the current candidate selected by the outer loop, a.get(j).
So for each iteration of the outer loop we will need to keep track of whether any iteration of the inner loop matched. We could use a local boolean named equalNumberFound, which we set to false at the start of each iteration of the outer loop.
In the inner loop, we check whether we've found an equal number, and if we have, set it to true. Make sure that you don't check a number against itself!
At the end of each iteration of the outer loop, we check equalNumberFound, and if it's still false we can return the current outer loop number, because we now know that no other number was equal.
You need to review what you know about while loops, as it seems you have some incorrect assumptions about how they behave.
One of the ways you could approach the problem is by sorting the list first then compare each element to its adjacent element since the elements are limited to occurring either once or twice. Since only one element occurs once, then the element without an identical adjacent element is the stop condition. This approach achieves O(log(N)) time complexity and O(1) space complexity.
public static int lonelyInteger(List<Integer> a) {
Collections.sort(a);
for (int i = 1; i < a.size(); i += 2) {
if (a.get(i - 1).intValue() != a.get(i).intValue()) return a.get(i - 1);
}
return a.get(a.size()-1);
}
You can make use of hashset. Iterate through the list of integers:
Add element to hashset, if integer is not present in the hashset.
Remove the integer element, if it is already present in the hashset
Now return the lone non-repeating integer in the hashset.
public static int lonelyinteger(List<Integer> a) {
Set<Integer> set = new HashSet<>();
for (int n : a) {
if (set.contains(n)) {
set.remove(n);
} else {
set.add(n);
}
}
return set.stream().findFirst().get();
}
A better solution without using Streams
public static int lonelyinteger(List<Integer> a) {
Set<Integer> s = new HashSet<>();
for (int num : a) {
if(!s.add(num)){
s.remove(num);
}
}
return new ArrayList<>(s).get(0);
}
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).
I'm trying to iterate over an Object array. Using the next() method works so I'm guessing that my iterator class and constructors are working.
For some reason i'm not getting any output while the hasNext() method is running.
Iterator it = hej.iterator();
Object j = it.next();
System.out.println(j);
while(it.hasNext()){
Object i = it.next();
System.out.println(i + " ");
}
With "hej" being my Object array.
My code for the next(); and hasNext() methods are as follows:
public class StackIterator implements Iterator<Object>{
// fields
private int element = 0;
private final Object[] elements;
private final int max;
// constructor
public StackIterator(Object[] values, int maxIndex) {
elements = values;
max = maxIndex;
}
// methods
public boolean hasNext() {
return element < max;
}
public Object next() {
return elements[element++];
}
}
The file that constructs the Object Array and the Object Array depends on an interface:
public interface Stack {
int size();
boolean isEmpty();
void push(Object element);
Object pop();
Object peek();
Iterator<Object> iterator();
}
The methods are then explained in another file:
public class StackExample implements Stack {
// fields
int length = 0;
Object[] arr;
// constructor
public StackExample() {arr = new Object[length];}
// method returns size of object array
public int size() {
return arr.length;
}
// method checks if object is empty
public boolean isEmpty() {
boolean result = false;
if (arr.length == 0){
result = true;
}
return result;
}
// method for push
public void push(Object element) {
newBiggerObj();
arr[0] = element;
}
// returns the first object of the stack
public Object pop() {
Object[] temp = new Object[arr.length-1];
Object first = arr[0];
for (int i = 0; i<arr.length-1; i++){
temp[i] = arr[i+1];
}arr = temp;
return first;
}
// returns the object on top of stack
public Object peek() {
if (isEmpty()){
try{
throw new Exception("Stack empty, can't peek!");
}
catch(Exception e){
return e.getMessage();
}
}
else {
Object first = arr[0];
return first;
}
}
// method for push method
private void newBiggerObj(){
Object[] temp = new Object[arr.length+1];
for (int i = 0; i<arr.length; i++){
temp[i+1] = arr[i];
}
arr = temp;
}
public String toString(){
String str = "";
for (int i = 0; i < arr.length; i++){
str = str + arr[i] + " , ";
}return str;
}
public Iterator<Object> iterator() {
return new StackIterator(arr, length);
}
}
What bothers me is that the method Iterator is within itself returning an instance of the class Stack Iterator. Which i posted above. So my real problem seems to be that my fields are not being given any value, since I am not myself giving the any values within the constructor.
My main method in which I'm testing all of this is as follows:
public class Teststack {
public static void main(String[] args){
// new instane of class StackExample
StackExample hej = new StackExample();
// test for the different methods
System.out.println(hej.isEmpty());
System.out.println(hej.size());
hej.push(4);
hej.push("hej");
hej.push(6);
hej.push(5);
System.out.println(hej.size());
System.out.println(hej.peek());
System.out.println(hej.pop());
System.out.println(hej.toString());
System.out.println(hej.isEmpty());
System.out.println("Testing Iterator: ");
// test for iterator
Iterator it = hej.iterator();
Object j = it.next();
System.out.println(j);
while(it.hasNext()){
Object i = it.next();
System.out.println(i + " ");
}
}
}
In your StackExample class, I don't see the length variable being updated when elements are pushed or popped. Due to this, length will always be 0 and calls to it.hasNext() will always return false.
You don't need to pass the length as a separate argument. You can find the array's length in the StackIterator constructor and use it.
Also note that since you're creating a new array on every push and pop, the iterator returned by StackExample#iterator() will become stale after every push/pop since it will work on an old copy/state of the stack.
The problem is here:
public Iterator<Object> iterator() {
return new StackIterator(arr, length);
}
length field is never changed, so its value is always 0. You can change the code to this:
public Iterator<Object> iterator() {
return new StackIterator(arr, arr.length);
}
Also, before retrieving elements from the iterator, you should always call it.hasNext. The fact you did this:
Iterator it = hej.iterator();
Object j = it.next();
And worked was just pure luck.
Apart of this, I can sense you have a bad design on your stack implementation. Here are some hints to improve your code:
The inner array should be initialized with a default size different than 0. E.g. 10 (as done in java.util.ArrayList implementation).
You should avoid creating a new array when adding (push) or removing (pop) an element from your stack. Instead of this, you should use the length field to control how many elements are in your stack.
The value of the new size should be based on another formula rather than array.length + 1. For example, try using something like int newSize = array.length / 2 * 3;.
Resize the inner array only when necessary. When calling push, do it only if you precisely need to increase the size of the array. When calling pop, do it if the current length of the array (this is, array.length) is far greater than the value of length field of your class.
Never forget to update the value of length on push and pop methods.
Couple of issues:
You are calling Object j = it.next(); after creating iterator and then check for hasNext. You are incrementing the element index. Hence if you just have one element, you wont enter the while loop. In addition, if your custom datastructure is empty i.e. array has no elements then you are prone to ArrayIndexOutOfBoundException.
You will always iterate and print n-1 elements instead to n elements.
Once you iterated, then your pointer will always point to last element and never get resetted. So very next time you wont be able to iterate over your elements. Its a one time iterator.
Try not to call
Object j = it.next() statement, but just while cycle. Seems you have an array of just 1 element.
There are a number of problems with this code:
In the StackIterator constructor there is no bounds checking on maxIndex. Callers can pass in a number greater than values.length, less that 0, etc.
In the next method, there is no check of the end condition, either directly or by calling hasNext(). Callers can keep calling next() and see elements beyond max or even get an ArrayIndexOutOfBoundsException, when they should be getting a NoSuchElementException.
The Stack class never increments or decrements its length field when elements are pushed or popped.
The Stack class tracks the length separately from the array, even though it always resizes the array on every push or pop, but Java arrays already know their size. (But see the next item.)
The Stack class resizes the array on every push or pop, which is very inefficient. Typically classes like this only resize the array when necessary, allowing 'slack' space, to give amortized constant time performance (see ArrayList). If you do this, however, it is necessary to null out popped items to avoid unintentional object retention.
The Stack adds and removes elements at the beginning of the array. This is incredibly inefficient since it means a O(n) reshuffling must be done on every push or pop.
The peek() method takes into account the possibility that the Stack may be empty, but the pop() method does not. A pop() on an empty Stack will throw an ArrayIndexOutOfBoundsException.
Stack is not a generic class. It holds Object. Users of the Stack will have to cast the return values from peek() or pop(), and it isn't type safe. In your example, you show a stack that is a heterogeneous mixture of String and Integer. This is a very Java 1.2 way of doing things, and while it isn't necessarily wrong, you should consider parameterizing Stack.
I want to rearrange an ArrayList by iterating through it and copying each element to a specific place in a new list.
In this case I want to move an element to the end of the list. For example, if the list is ABCDE and j == B then the new list should be ACDEB.
Here's my code:
private ArrayList<Job> schedule;
private ArrayList<Job> tempSchedule;
...
schedule = input;
tempSchedule = new ArrayList<Job>(schedule.size());
...
private void moveJob(int j) {
for(int i = 0; i < schedule.size(); i++) {
if(i == j) { //move to the end
tempSchedule.set(schedule.size()-1, schedule.get(i));
} else {
if(i > j && i <= schedule.size() -1) { //move one position back
tempSchedule.set(i - 1, schedule.get(i));
} else { //same position
tempSchedule.set(i, schedule.get(i));
}
}
}
schedule = tempSchedule;
u++;
}
Right now I get an IndexOutOfBoundsException: Index: 0, Size: 0 at tempSchedule.set
I guess the problem is with this line
tempSchedule = new ArrayList<Job>(schedule.size());
Also please explain how to make deep copies.
Edit: Thanks for all the answers. I got it to run by simply removing the item and adding it at the end, like suggested.
The reason I wanted to construct a new list is because I might have to do more complex rearrangements at some point.
First, go read the javadoc on ArrayList and collections.
new ArrayList(capacity) doesn't copy, it just allocates a list with that capacity. To copy the list (and it's not a clone, it's a by reference copy, again you need to go back to basics) would be new ArrayList(oldArrayList).
Secondly, Your test has size 0, so there's no objects in it, so get(0) (correctly and as per spec) throws an index out of bounds exception because your list is empty.
Beyond that, neither set nor get will modify the list, so if you had created your copy correctly and it's contents were ABCD and you executed that operation, it's contents would then be ABCB. what you want is.
X = tempSchedule.remove(i) // removes element at I
tempSchedule.add(X) // adds element to end of list
tempSchedule is initialized to be empty:
tempSchedule = new ArrayList<Job>(schedule.size());
You can't use set on an empty ArrayList. It expects the index you are replacing to already have a value.
You get the exception in this line - tempSchedule.set(i, schedule.get(i)); - when i==0.
set calls RangeCheck :
/**
* Checks if the given index is in range. If not, throws an appropriate
* runtime exception. This method does *not* check if the index is
* negative: It is always used immediately prior to an array access,
* which throws an ArrayIndexOutOfBoundsException if index is negative.
*/
private void RangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(
"Index: "+index+", Size: "+size);
}
As you can see, the index you pass to it must be smaller than the current size of the list.
The problem is that your tempSchedule list is empty. set() overwrites the element at the given position. If your list is empty, it can't do that.
This might be a little confusing since you wrote new ArrayList<Job>(schedule.size()). But the parameter you are passing doesn't set the size but the initial capacity, meaning the initial size of the underlying array, which can be used before it has to be resized.
Reason is when you define arrayList with size of schedule, its an empty list i.e. contains nothing.
So when you try to set an element (which is used to replace the existing element), it compares the index with size of your list and finds that index is 0 and size is 0 as well.
Note just by passing size as constructor, you are not changing the size of arrayList. So in order to avoid this, you need to use:
tempSchedule = new ArrayList<Integer>(schedule);
instead of
tempSchedule = new ArrayList<Integer>(schedule.size());
You have the IndexOutOfBoundsException because you are using schedule.size in your for loop while it's null you have to use tempSchedule.size instead.
And you are comparing i and j while you have to compare tempSchedule.get(i) and j.
You have a syntax fallacy as every other answer stated.
I'm more concerned on your approach.
Can't you just simply do:
private void moveJob(int j) {
Job toMove = tempSchedule.get(j);
tempSchedule.remove(j);
tempSchedule.add(toMove);
}
Or yet more concise:
private void moveJob(int j) {
tempSchedule.add(tempSchedule.remove(j));
}
I need to create a method that takes a param as maxValue. And loop through it from 0 but once it uses one index, it must not use it again.
Explanation:
Lets take an example, maxValue is 2000. Now it should go from 0 to 2000 but the start index keeps change by other thread. Like it can be 0 again or it can be 1900 or 1999, can be any number less than maxValue. So it should keep loop from starting index to end and then loop for the rest of items.
Here is what I have tried:
public int i = 0; //keep changes by other thread
public void DoStuff(int maxValue) {
HashSet<Integer> valuesSet = new HashSet<Integer>();
// fill hashset
for (int a = 0; a < maxValue; a++)
valuesSet.add(a);
for (; i < maxValue; i++) {
if (valuesSet.contains(i)) {
valuesSet.remove(i);
// SomeMethod(i);
}
if (valuesSet.isEmpty())// must check isEmpty first
break;
if (i == (maxValue - 1)) // reset i to 0 to use remaining items in hashset
i = 0;
}
}
I haven't tested this code but I can see the problem will come if other thread keep set i to 0 or some less value than maxValue and this loop will go infinite. While it should be something better. Any idea guys?
Edited :
Deep Example
i=0 and maxValue=2000
DoStuff gets called and when i reaches to 100 through loop, i got set by other thread to 1600, loop is keep going but again i got set to 30 by same other thread and then again and again it get set by other thread, Untill all the items in valuesSet get called in SomeMethod(i). But problem is, if 1 or more item left in valuesSet like 1998 or 1999 and i keep get set to lower like 0 or 10 or 100, the loop has very low chances to break or finish.
What I want is, if once a number(0 to maxValue) get called in SomeMethod, it must not get called again, while the starting number keep changes and SomeMethod must have called with all numbers till maxValue. If SomeMethod get called till maxValue and still numbers left, it should start again with lowest number.
Your requirements are not clear, but it seems like you are describing something that should be implemented as custom Iterator class. For example:
public class MyIterator<T> implements Iterator<T> {
private int maxValue;
private int pos;
private List<T> list;
public ListIterator(List<T> list, int maxValue) {
this.list = list;
this.maxValue = maxValue;
}
public synchronized T next() {
if (pos < list.size() && pos <= maxValue) {
return list.get(pos++);
} else {
throw ...
}
}
// etcetera.
}
You then provide an instance of this class to the specific threads that you want to be able to participate in the iteration. Other threads won't be able to interfere. Indeed other threads could use a different instance ... and iterate independently.
Note that the only differences between this custom iterator the one returned by List.iterator() are:
This one only iterates from zero to maxValue.
This one has synchronized methods so that it can be shared by multiple threads.
You could also add a reset method if that's what you need.