Is there a difference between Arrays.fill and actual fill - java

This question might appear trivial, but I am unable to find a solution to this problem for a few days.
Snippet 1 :
for(int i = 0; i < arr.length; i++){
arr[i] = new Bucket();
}
Snippet 2 :
Arrays.fill(arr, new Bucket());
Code with snippet 1 is executing as expected, but code that includes snippet 2 is not passing all the test cases.
I am expecting both the statements to do the same work internally. But the test cases show it is not. Any help to clarify this will be very helpful.

Think about what they do: in the loop you create a new object on every iteration. In the second you create one object and fill the array with it. They are totally different.
From documentation:
Assigns the specified Object reference to each element of the specified array of Objects.

Arrays.fill() uses the same object all time:
public static void fill(Object[] a, Object val) {
for (int i = 0, len = a.length; i < len; i++)
a[i] = val;
}
So entire array becomes filled with a single instance created once by new Bucket()

I am expecting both the statements to do the same work internally.
Snippet 2 is only creating one Bucket, and adding the same instance to every slot. So they are not the same, in Java 8+ you could use a lambda and something like
IntStream.range(0, arr.length).forEach(x -> arr[x] = new Bucket());
to fill the Bucket[] arr.

Related

Creating multiple objects using a for loop

I'm having difficulty in creating multiple objects in a for loop the object keeps being overwritten each time the loop is run.
for(i = 0 ; i < 10; i++){
Driver one = new Driver();
}
How do I make it so that new objects are created every time the loop is run, currently one just keeps being overwritten.
Sorry for the basic question i'm just new to programming.
You can do this using array:
int n = 10;
Driver[] driverArray = new Driver[n];
for(int i = 0 ; i < n; i++){
driverArray[i]= new Driver();
}
In your code, you are declaring a local reference to Driver class, and creating new Driver object in every iteration.
It doesn't work for two reasons:
1. You are declaring local reference in for-loop so the only place, when you can use it is this for-loop.
2. Even if you declare the reference outside the loop you would initialize it with new Driver object so after loop you would have the only one Driver insance - the last one.
For more about arrays you can read here.
Hope it helps.

Dynamic chaining "thenReturn" in mockito

I have a Tuple mock class, whose getString(0) and getString(1) methods are expected to be called n times. Instead of writing something like,
when(tuple.getString(0)).thenReturn(logEntries[0]).thenReturn(logEntries[1])...thenReturn(logEntries[n - 1])
manually, I tried the following:
OngoingStubbing stubbingGetStringZero = when(tuple.getString(0)).thenReturn(serviceRequestKey);
OngoingStubbing stubbingGetStringOne = when(tuple.getString(1)).thenReturn(logEntries[0]);
for (int i = 1; i < n; i++) {
stubbingGetStringZero = stubbingGetStringZero.thenReturn(serviceRequestKey);
stubbingGetStringOne = stubbingGetStringOne.thenReturn(logEntries[i]);
}
The expected result is that all calls to tuple.getString(0) should return the String serviceRequestKey and each call to tuple.getString(1) should return a different String logEntries[i] ie. ith invocation of tuple.getString(1) returns ith element of logEntries array.
However, due to some odd reason, things are getting mixed up, and second invocation to tuple.getString(1) returns the String serviceRequestKey instead of logEntries[1]. What am I missing here?
Well, the right way to do this would be:
import org.mockito.AdditionalAnswers;
String[] logEntry = // Some initialization code
List<String> logEntryList = Arrays.asList(logEntry);
when(tuple.getString(1)).thenAnswer(AdditionalAnswers.returnsElementsOf(logEntryList));
On each invocation, successive elements of logEntry array are returned. Thus, ith invocation of tuple.getString(1) returns ith element of logEntry array.
P.S: The example in documentation of returnsElementsOf (as of this writing) is not updated (it still uses ReturnsElementsOf example): http://docs.mockito.googlecode.com/hg/1.9.5/org/mockito/AdditionalAnswers.html#returnsElementsOf(java.util.Collection)it
If I understood well, you want your mock to return different results depending on the invocation (meaning result1 when invoked for the first time, result2 when invoked for the second time etc)- this can be accomplished with such thing
Mockito.when(tuple.getString(0)).thenReturn(serviceRequestKey,logEntries[0],logEntries[1])
With this you will get serviceRequestKey on first invocation, logEntries[0] on second etc...
If you want something more sophisticated, like change the return depending on the param in the method use thenAnswer() as shown here
Not sure I understand Mockito well enough to understand your example, but wouldn't you want something like:
Mockito.when(tuple.getString(0)).thenReturn(serviceRequestKey);
for(int i = 0;i < logEntries.length;i++) {
Mockito.when(tuple.getString(i+1)).thenReturn(logEntries[i]);
}
I know that post is older, but maybe it helps:
OngoingStubbing<Boolean> whenCollectionHasNext = when(mockCollectionStream.hasNext());
for (int i = 0; i < 2; i++) {
whenCollectionHasNext = whenCollectionHasNext.thenReturn(true);
}
whenCollectionHasNext = whenCollectionHasNext.thenReturn(false);

Copying a two dimensional array - still uses references?

I have got (IMHO) a strange behaviour in my code. I am currently implementing the minimax algorithm for a Tic Tac Toe game. In my "successor" method I want to determine all possible moves. Here's the code:
private ArrayList<TicTacToeState[][]> successor(final TicTacToeState[][] field, TicTacToeState s) {
ArrayList<TicTacToeState[][]> returnList = new ArrayList<TicTacToeState[][]>();
for (int i = 0; i < TicTacToeGame.FIELDSIZE; i++) {
for (int j = 0; j < TicTacToeGame.FIELDSIZE; j++) {
if (field[i][j] == TicTacToeState.Empty) {
TicTacToeState[][] currentCopy = new TicTacToeState[TicTacToeGame.FIELDSIZE][TicTacToeGame.FIELDSIZE];
System.arraycopy(field, 0, currentCopy, 0, field.length);
currentCopy[i][j] = s; // <- field seems to be referenced?!
returnList.add(currentCopy);
}
}
}
return returnList;
}
As you can see, I want to get all possible moves and save them into an arraylist. Unfortunately, when setting the value in "currentCopy", the "field" is also changed. But the field shouldn't be refrenced, because I copied the array. Where is the mistake? I have already tried using the clone() method on the two dimensional array -> same problem.
Thank you for any help.
(FYI, TicTacToeState is an enumeration including "Player1", "Player2" and "Empty")
Java uses shallow copies. That is, you get a copy but it isn't what you want here. You want a deep copy. Try manually copying each element into returnList and see what happens.
Another way to solve this is to make your move, recurse, then unmake the move. Then you don't need to copy the array at all.
You are using a a 2 dimensional array but only copying the first dimension of the array in your system array copy. I would suggest not doing all that copying though. Use something else to describe the possible moves perhaps. Note also that you are not copying the contents of the array, only the array.

Get the array from an AtomicLongArray

Using Java 1.6 and the AtomicLongArray, I'd like to "copy" the original AtomicLongArray into a new one. There is a constructor that takes an array (AtomicLongArray(long[])), so I thought I could just get the array from the original one and give it to the constructor.
Sadly, the actual long[] in the AtomicLongArray is private and there seem to be no getters for it. Is there any way to do this, meaning copy the values from one AtomicLongArray to another? I can't create my own class based on this class, as the sun.misc.Unsafe class is not available to me.
This is needed because I'm going to iterate over the values, and I don't want them modified by another thread during iteration. So I thought I could make a copy and use that for the iteration...
Thanks!
Phillip
I suspect you have to create your own long[] and populate it first, or just iterate over the original:
AtomicLongArray copy = new AtomicLongArray(original.length());
for (int i = 0; i < copy.length(); i++)
{
copy.set(i, original.get(i));
}
Note that although each individual operation in AtomicLongArray is atomic, there are no bulk operations - so there's no way of getting a "snapshot" of the whole array at time T. If you want that sort of behaviour, I believe you'll need to use synchronization.
This data structure allows concurrent updates to individual entries in the collection. There is not overall lock, so you can't prevent another thread changing the contents while you are iterating over it.
If you need this, you need a workaround, e.g. copy the array and loop again to check it hasn't changed. If changed, repeat. Or you need a collection which supports a global lock.
long[] copy = new long[original.length()];
boolean changed = true;
// repeat until we get an unchanged copy.
while(true) {
for (int i = 0; i < copy.length(); i++) {
long l = original.get(i);
changed |= copy[i] != l;
copy[i] = l;
}
if (!changed) break;
changed = false;
}
This is not completely safe, but may be enough for what you need.

Vector ArrayIndexOutOfBounds

I'm having an ArrayIndexOutofBounds exception with the following code.
The exception is thrown at the line where Node nodeJ = vect.get(j)
but it does not make sense to me since j is definitely smaller than i and Node nodeI = vect.get(i) does not throw any exception.
any help is appreciated.
public static Vector join(Vector vect) throws ItemNotFoundException {
Vector<Node> remain = vect;
for (int i = 1; i < vect.size(); i++) {
Node nodeI = vect.get(i);
for (int j = 0; j < i; j++) {//traverse the nodes before nodeI
Node nodeJ = vect.get(j);
if (nodeI.getChild1().getSeq().equals(nodeJ.getSeq())) {
nodeI.removeChild(nodeJ);
nodeI.setChild(nodeJ);
remain.remove(j);
}
if (nodeI.getChild2().getSeq().equals(nodeJ.getSeq())) {
nodeI.removeChild(nodeJ);
nodeI.setChild(nodeJ);
remain.remove(j);
}
}
}
return remain;
}
You are removing elements from the same vector you are iterating over, via an alias reference, remain. If you want to use a copy instead, you should have
Vector<Node> remain = new Vector<Node>(vect);
What happens if in your inner loop you remove more than i - j Nodes from the vector? You will end up with j > vect.size().
Probably best to change the condition in the second for loop to j < i && j < vect.size(), however I think there is something flawed about an algorithm which involves double-iterating over a collection to remove elements from it while you are iterating over it.
You're removing things from vect while you're iterating over it. Are you sure that's what you want to do?
Remember that this line:
Vector<Node> remain = vect;
does not create a copy of vect. Remove something from remain and it'll be removed from vect too, because the two names refer to the same actual object.
You should use Iterator. Look to documentation http://java.sun.com/docs/books/tutorial/collections/interfaces/collection.html
You can read:
Note that Iterator.remove is the only safe way to modify a collection during iteration; the behavior is unspecified if the underlying collection is modified in any other way while the iteration is in progress.
You are removing items from your vector.
Use some logging to output the contents of the vector on each iteration of the inner loop and you'll see what's going on.
When you remove an item from the vector (which you do), then the length of the vector changes. The problem is that the code after the removal has had so many nodes removed that it's now using indexes which are no longer valid.

Categories