code
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class SynchronizedObjEffectArea {
interface Func {
void run();
}
private volatile int index = 0;
private static final int size = 20000;
public static void main(String[] args) {
final List<Func> threadList = new ArrayList<>();
final SynchronizedObjEffectArea obj = new SynchronizedObjEffectArea();
for (int i = 0; i < size; i++) {
threadList.add(obj::task1);
threadList.add(obj::task2);
}
Collections.shuffle(threadList);
for (final Func thread : threadList) {
thread.run();
}
}
private void task1() {
synchronized (SynchronizedObjEffectArea.this) {
index = index + 1;
}
}
private void task2() {
synchronized (SynchronizedObjEffectArea.this) {
index = index + 1;
if (index == size * 2) {
System.out.println("index: " + index);
}
}
}
}
With the code like above, i usually can got the output "index: 40000" or sometimes can not.
By comment out the code Collections.shuffle(threadList);, the code works fine, it always output "index: 40000"
I confuse that what shuffle function do cause the result like above? Can anyone explain this?
I don't think you're really asking about what Collections.shuffle does in general: I think you're asking why Collections.shuffle affects the output:
You are creating a load of tasks of two kinds: one of them increments a value ("kind 1"); the other increments a value and sometimes prints a message ("kind 2"). These are put into a list, and executed sequentially.
If you put an equal number of these two kinds of tasks into a list, shuffle them, and execute them sequentially, the item at a position is going to be a "kind 1" task 50% of the time, and a "kind 2" task the rest of the time.
Since "kind 2" tasks only prints for a specific value, you will only get something printed if it is a "kind 2" task at position 2 * size - 1, which will be 50% of the time.
If you don't shuffle them, but add "kind 1" and "kind 2" in turn, the item at position 2 * size - 1 will always be a "kind 2", so it will always print.
Collections.shuffle() Randomly permutes the specified list using a default source of randomness. All permutations occur with approximately equal likelihood.
So if tasks ar shuffled, sometimes task2 run first and then output is different.
This is the javadoc and source code for java.util.Collections.shuffle():
/**
* Randomly permute the specified list using the specified source of
* randomness. All permutations occur with equal likelihood
* assuming that the source of randomness is fair.<p>
*
* This implementation traverses the list backwards, from the last element
* up to the second, repeatedly swapping a randomly selected element into
* the "current position". Elements are randomly selected from the
* portion of the list that runs from the first element to the current
* position, inclusive.<p>
*
* This method runs in linear time. If the specified list does not
* implement the {#link RandomAccess} interface and is large, this
* implementation dumps the specified list into an array before shuffling
* it, and dumps the shuffled array back into the list. This avoids the
* quadratic behavior that would result from shuffling a "sequential
* access" list in place.
*
* #param list the list to be shuffled.
* #param rnd the source of randomness to use to shuffle the list.
* #throws UnsupportedOperationException if the specified list or its
* list-iterator does not support the <tt>set</tt> operation.
*/
#SuppressWarnings({"rawtypes", "unchecked"})
public static void shuffle(List<?> list, Random rnd) {
int size = list.size();
if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {
for (int i=size; i>1; i--)
swap(list, i-1, rnd.nextInt(i));
} else {
Object arr[] = list.toArray();
// Shuffle array
for (int i=size; i>1; i--)
swap(arr, i-1, rnd.nextInt(i));
// Dump array back into list
// instead of using a raw type here, it's possible to capture
// the wildcard but it will require a call to a supplementary
// private method
ListIterator it = list.listIterator();
for (int i=0; i<arr.length; i++) {
it.next();
it.set(arr[i]);
}
}
}
So, as out common knowledge of the English language tells us, shuffle will randomly re-order the contents of the Collection you specify.
That's also what the javadoc says.
So seeing you have this problem, next time
Look up the English term in a translator or dictionary
Use an IDE. That will show you the javadoc for the methods, and as a bonus it will do the formatting of your source code for you
Run a test with 3-10 items on a list, this will also show you what happens
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I did some research and wrote the following article: http://www.heavyweightsoftware.com/blog/linkedlist-vs-arraylist/ and wanted to post a question here.
class ListPerformanceSpec extends Specification {
def "Throwaway"() {
given: "A Linked List"
List<Integer> list
List<Integer> results = new LinkedList<>()
when: "Adding numbers"
Random random = new Random()
//test each list 100 times
for (int ix = 0; ix < 100; ++ix) {
list = new LinkedList<>()
LocalDateTime start = LocalDateTime.now()
for (int jx = 0; jx < 100000; ++jx) {
list.add(random.nextInt())
}
LocalDateTime end = LocalDateTime.now()
long diff = start.until(end, ChronoUnit.MILLIS)
results.add(diff)
}
then: "Should be equal"
true
}
def "Linked list"() {
given: "A Linked List"
List<Integer> list
List<Integer> results = new LinkedList<>()
when: "Adding numbers"
Random random = new Random()
//test each list 100 times
for (int ix = 0; ix < 100; ++ix) {
list = new LinkedList<>()
LocalDateTime start = LocalDateTime.now()
for (int jx = 0; jx < 100000; ++jx) {
list.add(random.nextInt())
}
long total = 0
for (int jx = 0; jx < 10000; ++jx) {
for (Integer num : list) {
total += num
}
total = 0
}
LocalDateTime end = LocalDateTime.now()
long diff = start.until(end, ChronoUnit.MILLIS)
results.add(diff)
}
then: "Should be equal"
System.out.println("Linked list:" + results.toString())
true
}
def "Array list"() {
given: "A Linked List"
List<Integer> list
List<Integer> results = new LinkedList<>()
when: "Adding numbers"
Random random = new Random()
//test each list 100 times
for (int ix = 0; ix < 100; ++ix) {
list = new ArrayList<>()
LocalDateTime start = LocalDateTime.now()
for (int jx = 0; jx < 100000; ++jx) {
list.add(random.nextInt())
}
long total = 0
for (int jx = 0; jx < 10000; ++jx) {
for (Integer num : list) {
total += num
}
total = 0
}
LocalDateTime end = LocalDateTime.now()
long diff = start.until(end, ChronoUnit.MILLIS)
results.add(diff)
}
then: "Should be equal"
System.out.println("Array list:" + results.toString())
true
}
}
Why does ArrayList outperform LinkedList by 28% for sequential access when LinkedList should be faster?
My question is different from When to use LinkedList over ArrayList? because I'm not asking when to choose it, but why it's faster.
Array-based lists, as Java ArrayList, use much less memory for the same data amount than link-based lists (LinkedList), and this memory is organized sequentially. This essentially decreases CPU cache trashing with side data. As soon as access to RAM requires 10-20 times more delay than L1/L2 cache access, this is causing sufficient time difference.
You can read more about these cache issues in books like this one, or similar resources.
OTOH, link-based lists outperform array-based ones in operation like insering to middle of list or deleting there.
For a solution that have both memory economy (so, fast iterating) and fast inserting/deleting, one should look at combined approaches, as in-memory B⁺-trees, or array of array lists with proportionally increased sizes.
From LinkedList source code:
/**
* Appends the specified element to the end of this list.
*
* <p>This method is equivalent to {#link #addLast}.
*
* #param e element to be appended to this list
* #return {#code true} (as specified by {#link Collection#add})
*/
public boolean add(E e) {
linkLast(e);
return true;
}
/**
* Links e as last element.
*/
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
From ArrayList source code:
/**
* Appends the specified element to the end of this list.
*
* #param e element to be appended to this list
* #return <tt>true</tt> (as specified by {#link Collection#add})
*/
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
So linked list has to create new node for each element added, while array list does not. ArrayList does not reallocate/resize for each new element, so most of time array list simply set object in array and increment size, while linked list does much more work.
You also commented:
When I wrote a linked list in college, I allocated blocks at a time and then farmed them out.
I do not think this would work in Java. You cannot do pointer tricks in Java, so you would have to allocate a lot of small arrays, or create empty nodes ahead. In both cases overhead would probably be a bit higher.
Why does ArrayList outperform LinkedList by 28% for sequential access when LinkedList should be faster?
You're assuming that, but don't provide anything to back it up. But it's not really a great surprise. An ArrayList has an array as the underlying data store. Accessing this sequentially is extremely fast, because you know exactly where every element is going to be. The only slowdown comes when the array grows beyond a certain size and needs to be expanded, but that can be optimised.
The real answer would probably be: check the Java source code, and compare the implementations of ArrayList and LinkedList.
One explanation is that your base assumption (that multiplication is slower than memory fetches) is questionable.
Based on this document, a AMD Bulldozer takes 1 clock cycles to perform a 64 bit integer multiply instruction (register x register) with 6 cycles of latency1. By contrast, a memory to register load takes 1 clock cycle with 4 cycles of latency. But that assumes that you get a cache hit for the memory fetch. If you get a cache miss, you need to add a number of cycles. (20 clock cycles for an L2 cache miss, according to this source.)
Now that is just one architecture, and others will vary. And we also need to consider other issues, like constraints on the number of multiplications that can be overlapped, and how well the compiler can organize the instructions to get them minimize instruction dependencies. But the fact remains that for a typical modern pipelined chip architecture, the CPU can execute integer multiplies as fast as it can execute memory to register moves, and much faster if there are more cache misses in the memory fetches.
Your benchmark is using lists with 100,000 Integer elements. When you look at the amount of memory involved, and the relative locality of the heap nodes that represent the lists and the elements, the linked list case will use significantly more memory, and have correspondingly worse memory locality. That will lead to more cache misses per cycle of the inner loop, and worse performance.
Your benchmark results are not surprising2 to me.
The other thing to note is that if you use Java LinkedList, a separate heap node is used to represent the list nodes. You can implement your own linked lists more efficiently if your element class has its own next field that can be used to chain the elements. However, brings its own limitations; e.g. an element can only be in one list at a time.
Finally, as #maaartinus points out, a full IMUL is not required in the case of a Java ArrayList. When reading or writing the ArrayList's array, the indexing multiplication will be either x 4 or x 8 and that can be performed by a MOV with one of the standard addressing modes; e.g.
MOV EAX, [EDX + EBX*4 + 8]
This multiplication can be done (at the hardware level) by shifting with much less latency than 64 bit IMUL.
1 - In this context, the latency is the number of cycles delay before the result of the instruction is available ... to the next instruction that depends on it. The trick is to order the instructions so that other work is done during the delay.
2 - If anything, I am surprised that LinkedList appears to be doing so well. Maybe calling Random.nextInt() and autoboxing the result is dominating the loop times?
I am trying to understand how Collections.binarySearch work in Java.
I don't quite understand the output I get.
public static void main(String args[]) {
// create arraylist
ArrayList<String> arlst=new ArrayList<String> ();
arlst.add("A");
arlst.add("D");
arlst.add("C");
arlst.add("B");
arlst.add("E");
int index=Collections.binarySearch(arlst, "D", Collections.reverseOrder());
System.out.println(index);
}
}
The output of this code is -1.
And when the elements have been inserted at this order
arlst.add("D");
arlst.add("E");
arlst.add("C");
arlst.add("B");
arlst.add("A");
I get 0 as a result. I thought the negative number was a result if the element was not found. Could anybody please clarify the output I receive?
Your data must be sorted according to the given comparator for the binary search to work as intended. (If it's not, the behavior is undefined.)
The list must be sorted into ascending order according to the specified comparator (as by the sort(List, Comparator) method), prior to making this call.
If the data is indeed sorted, the method will return the index of the sought element (if it's found) otherwise (-(insertion point) - 1), as specified in the documentation.
Example:
// Make sure it's sorted
Collections.sort(arlst, Collections.reverseOrder());
int index=Collections.binarySearch(arlst, "D", Collections.reverseOrder());
System.out.println(index); // prints 1
Just to make it clearer - why the output is -1. Yes, you didn't sort it first is a big mistake. But here are some other things to take clear as well.
As #aioobe mentioned in his answer, but he didn't make it clear enough though I think. What does (-(insertion point) - 1) mean? Here is what the doc says.
The index of the search key, if it is contained in the list; otherwise, (-(insertion point) - 1). The insertion point is defined as the point at which the key would be inserted into the list: the index of the first element greater than the key, or list.size() if all elements in the list are less than the specified key. Note that this guarantees that the return value will be >= 0 if and only if the key is found.
So to make the answer more clear: -1 = -0 - 1
What I want to underline here is that the output maybe -2 or -3 or whatever. Because if all elements in the list are less than the specified key, the output will be -list.size() - 1.
■ Searches are performed using the binarySearch() method.
■ Successful searches return the int index of the element being searched.
■ Unsuccessful searches return an int index that represents the insertion point. The insertion point is the place in the collection/array where the element would be inserted to keep the collection/array properly sorted.
* Return values and 0 indicate successful searches
* Negative numbers to indicate insertion points
* The first available insertion point is -1. Therefore,the actual insertion point is represented as (-(insertion point) -1)
Here is the inner workings of the binarySearch method:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package binarysearch;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
public class BinarySearch {
static ArrayList<String> strings;
public static void main(String[] args) {
String sample = "a quick brown fox jumped right over the lazy dog while an active lion was nowhere in sight";
String[] simpleArray = sample.split(" ");
strings = new ArrayList(Arrays.asList(simpleArray));
Collections.sort(strings);
// Enter a search string; here it is "lazy"
binarySearch(strings, "lazy");
System.out.println("");
// Print the Array contents for convenience
printArrayList(strings);
}
static void printArrayList(ArrayList<String> strings) {
int i = 0;
for (String s: strings) {
i++;
System.out.println(i + s );
}
}
static void binarySearch (ArrayList<String> strings, String searchString) {
boolean debug = true;
int low = 0;
int high = strings.size();
int mid = 0;
while (low <= high) {
// The > symbol marks the hits before search is concluded
System.out.print(">");
mid = (high + low) / 2;
int comparison = strings.get(mid).compareToIgnoreCase(searchString);
if (comparison > 0) {
high = mid - 1;
} else if (comparison < 0) {
low = mid + 1;
} else {
int temp = mid;
System.out.println("Found '" + searchString + "' at: " + (temp + 1) );
break;
}
}
}
}
I am seeking guidance in the respect of optimising code. The code I have written is for a text-based game in which you type in commands into a command bar. One feature I wished to incorporate into my interface was the ability to scroll through a history of one's last 100 commands entered using the up and down arrow keys so that it would be more convenient for the user to play the game.
I have designed a class in which uses a String[] that will store each new entry in the second position (Array[1]) and move all entries back one position while the first position of the array (Array[0]) is just a blank, empty string. The code initialises the array to have 101 values to compensate for the first position being a blank line.
When a user inputs 0 - 100 in that order, it should then give me the reverse of the order (almost like a last in, first out kind of situation, but storing the last 100 values as opposed to removing them once they are accessed), and since 0 - 100 is 101 values, the last value will be overwritten.
Thus, scrolling up through the history, it would give me 100, 99, 98, ..., 2, 1. If I were to select 50 from the list, it would then be 50, 100, 99, ..., 3, 2. The code indeed does this.
The code is listed below:
public class CommandHistory {
private String[] history;
private final int firstIndex = 1;
private static int currentIndex = 0;
/**
* Default constructor, stores last 100 entries of commands plus the blank
* entry at the first index
*/
public CommandHistory() {
history = new String[101];
}
/**
* Constructor with a capacity, stores the last (capacity) entries of
* commands plus the blank entry at the first index
*
* #param capacity
* Capacity of the commands history list
*/
public CommandHistory(int capacity) {
history = new String[capacity + 1];
}
/**
* Returns the size (length) of the history list
*
* #return The size (length) of the history list
*/
private int size() {
return history.length;
}
/**
* Adds a command to the command history log
*
* #param command
* Command to be added to the history log
*/
public void add(String command) {
history[0] = "";
if (!command.equals("")) {
for (int i = firstIndex; i < size();) {
if (history[i] == null) {
history[i] = command;
break;
} else {
for (int j = size() - 1; j > firstIndex; j--) {
history[j] = history[j - 1];
}
history[firstIndex] = command;
break;
}
}
currentIndex = 0;
}
}
/**
* Gets the previous command in the history list
*
* #return The previous command from the history list
*/
public String previous() {
if (currentIndex > 0) {
currentIndex--;
}
return history[currentIndex];
}
/**
* Gets the next command in the history list
*
* #return The next command from the history list
*/
public String next() {
if (currentIndex >= 0 && (history[currentIndex + 1] != null)) {
currentIndex++;
}
return history[currentIndex];
}
/**
* Clears the command history list
*/
public void clear() {
for (int i = firstIndex; i < size(); i++) {
history[i] = null;
}
currentIndex = 0;
}
/**
* Returns the entire command history log
*/
public String toString() {
String history = "";
for (int i = 0; i < size(); i++) {
history += this.history[i];
}
return history;
}
}
In my interface class, once the user types something into the command bar and hits enter, it will get the text currently stored in the bar, uses the add method to add it to the history, parses the command via another class, and then sets the text in the bar to blank.
Pressing the up arrow calls the next method which scrolls up the list, and the down arrow calls the previous method which scrolls down the list.
It seems to work in every way I wish it to, but I was wondering if there was some way to optimise this code or perhaps even code it in a completely different way. I am making this game to keep myself practiced in Java and also to learn new and more advanced things, so I'd love to hear any suggestions on how to do so.
The comments to your question have already pointed out that you are somehow trying to reinvent the wheel by implementing functionality that the standard Java class library already provides to some extent (see LinkedList/Queue and Arraylist). But since you say you want to keep yourself practiced in Java I guess it is perfectly fine if you try to implement your own command history from scratch.
Here are some of my observations/suggestions:
1) It is not necessary and very counter-intuitive to declare a final first index of 1. It would be easy to start with a default index of 0 and add corresponding checks where necessary.
2) Forget about your private size() method - it is just returning the length of the internal array anyway (i.e. the initial capacity+1). Instead consider adding a public size() method that returns the actual number of added commands and internally update the actual size when adding new commands (see e.g. java.util.ArrayList for reference).
3) At the moment every call to add(String command) will set history[0] = "", which is not necessary. If you want the first index to be "", set it in the constructor. This is also a clear sign, that it would perhaps be better to start with an initial index of 0 instead of 1.
4) A minor issue: "if (!command.equals(""))" during your add method is perhaps OK for such a specialized class but it should definitely be commented in the documentation of the method. Personally I would always let the calling class decide if an empty "" command is considered valid or not. Also this method will throw an undocumented NullPointerException, when null is used as an argument. Consider changing this to "if (!"".equals(command))" or throw an IllegalArgumentException if null is added.
5) "if (history[i] == null)" during the add method is completely unnecessary, if you internally keep a pointer to the actual size of the commands - this is actually a special case that will only be true, when the very first command is added to the command history (i.e. when it's actual size == 0).
6) Having two nested for loops in your add method implementation is also unnecessary, if you keep a pointer to the actual size (see example below)
7) I would reconsider if it is necessary to keep a pointer to the current index in the command history. Personally I would avoid storing such a pointer and leave these details to the calling class - i.e. remove the previous and next methods and either provide a forward/backward Iterator and/or a random access to the index of the available commands. Interestingly, when this functionality is removed from your command history class, it actually comes down to either an implementation of a LinkedList or an ArrayList- whichever way you go. So in the end using one of the built in Java collections would actually be the way to go.
8) Last but nor least I would reconsider if it is useful to insert added commands at the beginning of the list - I believe it would be more natural to append them to the end as e.g. ArrayList does. Adding the commands to the end would make the swapping of all current commands during each call to add() unnecessary...
Here are some of the suggested changes to your class (not really tested...)
public class CommandHistory {
private String[] history;
private int size;
private static int currentIndex = 0;
/**
* Default constructor, stores last 100 entries of commands plus the blank
* entry at the first index
*/
public CommandHistory() {
this(100);
}
/**
* Constructor with a capacity, stores the last (capacity) entries of
* commands plus the blank entry at the first index
*
* #param capacity
* Capacity of the commands history list
*/
public CommandHistory(int capacity) {
history = new String[capacity];
}
/**
* Returns the size (length) of the history list
*
* #return The size (length) of the history list
*/
public int size() {
return size;
}
/**
* Adds a command to the command history log
*
* #param command
* Command to be added to the history log
*/
public void add(String command) {
if (!"".equals(command)) {
if (this.size < history.length) {
this.size++;
}
for (int i = size-1; i >0; i--) {
history[i] = history[i-1];
}
history[0] = command;
currentIndex = 0;
}
}
/**
* Gets the previous command in the history list
*
* #return The previous command from the history list
*/
public String previous() {
if (currentIndex >= 0 && currentIndex < size-1) {
currentIndex++;
}
return history[currentIndex];
}
/**
* Gets the next command in the history list
*
* #return The next command from the history list
*/
public String next() {
if (currentIndex > 0 && currentIndex < size) {
currentIndex--;
}
return history[currentIndex];
}
/**
* Clears the command history list
*/
public void clear() {
for (int i = 0; i < size; i++) {
history[i] = null;
}
currentIndex = 0;
}
/**
* Returns the entire command history log
*/
public String toString() {
String history = "";
for (int i = 0; i < size; i++) {
history += this.history[i] + ", ";
}
return history;
}
}
Well, I guess I have invested far too much time for this, but I learned quite a bit myself on the way - so thanks ;-)
Hope some of this is useful for you.
I am trying to program an example of a RadixSort in Java, and while I understand how the algorithm works I am running into a few issues with my implementation of a Linked List of Queues.
I believe my issue is when when I update the linked list at the nth position with a new Queue as it's value. I believe I am using the same Queue for each nodes update and that is causing me to get the same values for every node in my linked list.
So when starting with an array of int[] theArray = {4,3,5,9,7,2,4,1,6,5};
I end up with a linked list of 10 nodes each consisting a queue of:{4,3,5,9,7,2,4,1,6,5}
I thought by using the new keyword it would create a fresh instance but it seems to be carrying over the old values each iteration.
Can someone either explain or point me in the right direction to understanding why this is happening?
EDIT: (Forgot to attach code)
package radixsort;
import java.util.*;
/**
* #author dlanz
*/
public class RadixSort {
public static void main(String[] args) {
int[] theArray = {4,3,5,9,7,2,4,1,6,5};
RadixSort theSort = new RadixSort();
System.out.println(Arrays.toString(theArray)); //Outputs the original array
theSort.sort(theArray);
System.out.println(Arrays.toString(theArray)); //Outputs the original array (no modifictions)
}
public void sort(int[] theArray) {
int significant;
int curVal;
int modulo = 10;
int ofInterest = 1;
LinkedList<Queue> lists = new LinkedList<>();
Queue<Integer> queue = new LinkedList<>();
int max = theArray[0];
for(int i = 0; i < theArray.length; i++) {
if ( theArray[i] > max) {
max = theArray[i];
}
}
significant = String.valueOf(max).length();
Queue<Integer> thisQueue;
for(int j = 1; j <= significant; j++){
lists.clear();
for(int i = 0; i < 10; i++){
lists.add(i, queue);
}
System.out.println(lists); //Outputs a list of 10 elements each with a value of null
for(int value : theArray){
curVal = value % modulo;
curVal = curVal / ofInterest;
System.out.println(curVal); //Correctly outputs the expected result
System.out.println(lists.get(curVal)); //With each iteration this outputs 10 elements each with a queue of all values.
thisQueue = new LinkedList<>();
thisQueue = lists.get(curVal);
thisQueue.add(value);
lists.set(curVal, thisQueue);// This seems to insert the generated queue into every linked lists node.
}
int k = 0;
for(int i = 0; i < 10; i++){
Queue<Integer> curQueue = lists.get(i);
if(!curQueue.isEmpty()){
theArray[k] = curQueue.remove();
k++;
}
}
ofInterest = ofInterest * 10;
modulo = modulo * 10;
}
}
}
EDIT 2:
I've been playing around with it, and it seems as if thisQueue, lists and queue are shared. When I perform certain actions on thisQueue such as thisQueue.add(1), the value of '1' is added across the board. If I do the same on lists with lists.add(1) every node in lists is populated with the value 1.
I remember reading something about object values being passed by reference (not the objects themselves though), can this have any thing to do with what I am experiencing?
Edit 3:
I've also noticed that if I use literals instead of variables in the .add() lines such as
thisQueue.add(value);
The values do not duplicate as mentioned in EDIT 2. I tried to cast the variables used as int even though they were declared as Int, but still got the same results.
Oddly enough I appreciate how no one responded to this question. I figured it out on my own while creating a set of sample code and formulating a less specific question. But I will not forget this, for a very long time.
What was happening was in the portion of code where I loop through and create nodes 0-9 in my Linked List
for(int i = 0; i < 10; i++){
lists.add(i, queue);
}
I was adding a reference to the very same Queue. So regardless of the use of the other Queues/.clear() I was essentially pulling the reference to that original Queue on this line
thisQueue = lists.get(curVal);
While I made a few changes along the way, all that really had to be done was change the loop to
for(int i = 0; i < 10; i++){
queue = new LinkedList<>();
lists.add(i, queue);
}
and change
Queue<Integer> queue = new LinkedList<>();
To just
Queue<Integer> queue
I had thought of explicitly creating 10 Separate Queues and then using a switch in the code to decide which queue should be used. This did not seem very flexible and would have been very tedious. At the same time I realized that creating a new Queue for each iteration is very costly. I would be creating as many objects as are in the array, in this case 10, but that could be 100, 1000, 1000000. By using (correct me if I'm wrong) anonymous objects I was able to create only as many objects as needed (1 for each element in the linked lists).
I recently found myself needing to be sure my list wasn't in order. Hibernate was nice enough to return it in perfect order. Silly hibernate, not reading my mind.
I looked at my Java API and it tells me its shuffle method does this:
Randomly permutes the specified list using a default source of randomness.
Being the curious george that I am, I want to know what exactly this means. Is there a math course I can take to learn this? Can I see the code? Java, what are you doing to my ArrayList?!?!?
To be more specific, which math concepts are being used here?
Yes, you can look at the code; it basically does a Fisher-Yates shuffle. Here it is (thanks OpenJDK, and yay for open source :-P):
public static void shuffle(List<?> list, Random rnd) {
int size = list.size();
if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {
for (int i=size; i>1; i--)
swap(list, i-1, rnd.nextInt(i));
} else {
Object arr[] = list.toArray();
// Shuffle array
for (int i=size; i>1; i--)
swap(arr, i-1, rnd.nextInt(i));
// Dump array back into list
ListIterator it = list.listIterator();
for (int i=0; i<arr.length; i++) {
it.next();
it.set(arr[i]);
}
}
}
The swap method:
private static void swap(Object[] x, int a, int b) {
Object t = x[a];
x[a] = x[b];
x[b] = t;
}
The Collections JavaDoc gives some information on the shuffle method used.
This implementation traverses the list backwards, from the last element up to the second, repeatedly swapping a randomly selected element into the "current position". Elements are randomly selected from the portion of the list that runs from the first element to the current position, inclusive.
So it starts at the end and walks the list backwards. At each element it stops and swaps the current element with a preceding element from the list. The "default source of randomness" in this case is probably a Random object created with a default seed.