Why HashSet in my program is ordered (Java)? [duplicate] - java

Why do the second and third sets preserve order:
Integer[] j = new Integer[]{3,4,5,6,7,8,9};
LinkedHashSet<Integer> i = new LinkedHashSet<Integer>();
Collections.addAll(i,j);
System.out.println(i);
HashSet<Integer> hi = new HashSet<Integer>(i);
System.out.println(hi);
LinkedHashSet<Integer> o = new LinkedHashSet<Integer>(hi);
System.out.println(o);
Here's the output I get:
3,4,5,6,7,8,9
3,4,5,6,7,8,9
3,4,5,6,7,8,9

The second one (just using HashSet) is only a coincidence. From the JavaDocs:
This class implements the Set interface, backed by a hash table (actually a HashMap instance). It makes no guarantees as to the iteration order of the set; in particular, it does not guarantee that the order will remain constant over time. This class permits the null element.
The third one (LinkedHashSet) is designed to be like that:
Hash table and linked list implementation of the Set interface, with predictable iteration order. This implementation differs from HashSet in that it maintains a doubly-linked list running through all of its entries. This linked list defines the iteration ordering, which is the order in which elements were inserted into the set (insertion-order). Note that insertion order is not affected if an element is re-inserted into the set. (An element e is reinserted into a set s if s.add(e) is invoked when s.contains(e) would return true immediately prior to the invocation.)

#Behrang's answer is good but to be more specific, the only reason why the HashSet seems to be in the same order as the LinkedHashSet is that integer.hashCode() happens to be the integer value itself so the numbers happen to be in order in the HashSet internal storage. This is highly implementation specific and as #Behrang says, really a coincidence.
For example, if you use new HashSet<>(4) which sets the initial number of buckets to be 4 (instead of 16) then you might have gotten the following output:
HashSet<Integer> hi = new HashSet<Integer>(4);
...
[3, 4, 5, 6, 7, 8, 9]
[8, 9, 3, 4, 5, 6, 7]
[8, 9, 3, 4, 5, 6, 7]
If you had stuck in values >= 16, you might get something like this:
Integer[] j = new Integer[] { 3, 4, 5, 6, 7, 8, 9, 16 };
...
[3, 4, 5, 6, 7, 8, 9, 16]
[16, 3, 4, 5, 6, 7, 8, 9]
[16, 3, 4, 5, 6, 7, 8, 9]

Related

Java 8 functional way of getting consecutive numbers of a list

For example I have a list of integers, as List(1,2,3,4,5,6,7)
I want to get all of the combinations of consectuive 3 numbers in Java 8 more functional way to learn Java 8. (I know how to do it in a imperative way)
So the result for above can be a list of list as:
List(List(1,2,3), List(2,3,4), List(3,4,5), List(4,5,6), List(5,6,7))
Thanks
You can do it using List.subList while iterating over it:
final int subListSize = 3;
List<Integer> list = List.of(1, 2, 3, 4, 5, 6, 7);
List<List<Integer>> sublists = IntStream.rangeClosed(0, list.size() - subListSize)
.mapToObj(i -> list.subList(i, i + subListSize))
.collect(Collectors.toList());
You can also do it using the jOOλ library and its Seq.sliding() method (Seq is a sequential Stream):
List<Integer> list = List.of(1, 2, 3, 4, 5, 6, 7);
List<List<Integer>> sublists = Seq.seq(list)
.sliding(3)
.map(Collectable::toList)
.toList();
which yields:
[[1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6], [5, 6, 7]]
Note that:
nullpointer's solution has better performance (no new ArrayLists are created)
my solution is more readable (but you can always extract nullpointer's to a function like List<List<T>> sublists(List<T> list, int sublistSize)
my solution is independent of the original list while nullpointer's is a list of views of original list
usually, neither original list nor created sublists are modified afterwards so it doesn't matter (and it's good for performance)
however, if any were to be modified, nullpointer's solution will reflect those changes (or will even break if elements are removed from the original list)
to alleviate this, add an extra .map(List::copyOf) after mapToObj in his solution (or .map(ArrayList::new) if you want mutable results)

Why does list1.remove(0) give the first element in the list?

In a java course homework I was asked to describe what the following code does:
while (!list1.isEmpty()) {
list2.add(list2.size(), list1.remove(0));
}
At first I thought this is actually removing the first element of list1, then add the remaining right behind list2.
But after I run a simulation program as following:
import java.util.*;
public class testQ1
{
public static void main(String[] args)
{
List<Integer> list1 = new ArrayList<>(Arrays.asList(1,2,3,4));
System.out.println(list1);
List<Integer> list2 = new ArrayList<>(Arrays.asList(5,6,7,8));
System.out.println(list2);
while (!list1.isEmpty())
{
list2.add(list2.size(), list1.remove(0));
}
System.out.println(list2);
}
}
It gives me the result:
[1, 2, 3, 4]
[5, 6, 7, 8]
[5, 6, 7, 8, 1, 2, 3, 4]
So I try to print "list1.remove(0)" before the while loop to see what it is. Then the result becomes:
[1, 2, 3, 4]
[5, 6, 7, 8]
1
[5, 6, 7, 8, 2, 3, 4]
Now it prints "1" as what "list1.remove(0)" is. And merge the remaining list1 into list2 just as I thought before.
From What I know, remove(int index) method is used to removes the element at the specified position in this list.
My question then is: What exactly does list.remove(int index) give as a result?
Thanks!
List::remove returns the element that was removed. You removed a 1, so that's what was returned.
Always check the docs first for questions like this. The documentation of the method explains what the return value represents. With a library as mature as Java's, the docs will explain 99% of your questions.
Just remove the element, then return the list.

I wanted to add an element to my array after sorting the array

Here is my code
import java.util.*;
public class ArrayExample {
public static void main(String[] args) {
Integer arr[] = {5,4,3,2,15,8,9};
List<Integer> list = Arrays.asList(arr);
Collections.sort(list);
System.out.println(list);
list.add(6);// here I am adding 6 to my array.
System.out.println(list);
// Here I should get output as [2,3,4,5,6,8,9,15]
}
}
You can't because this declaration :
List<Integer> list = Arrays.asList(arr);
From documentation :
Arrays.asList Returns a fixed-size list backed by the specified array. (Changes to the returned list "write through" to the array.)
This method acts as bridge between array-based and collection-based
APIs, in combination with Collection.toArray(). The returned list is
serializable and implements RandomAccess.
for that you can't add to this list, even if you try to remove list.remove(index); this not work.
so to solve your problem you can use :
List<Integer> list = new ArrayList<>();//declare the list
for(Integer i : arr){
list.add(i);//add element by element to the list
}
Or simply you can use :
List<Integer> list = new ArrayList<>(Arrays.asList(arr));
//----------------------------------^------------------^
If you want the array to stay sorted, you will have to sort it after each insert.
However, using a binary search, you could also find the index i where the item should be inserted and insert it there using list.add(i,6). Which would be more efficient.
No you cannot add, as you are using Arrays.asList(arr);
List<Integer> list = Arrays.asList(arr);
asList returning a fixed-size list, you cannot add any element in that, once the list is formed.
You may get java.lang.UnsupportedOperationException
[2, 3, 4, 5, 8, 9, 15]
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
at Test.main(Test.java:14)
You can add an element without using a list by using 2 arrays: a source array src and a destination array dest. The destination array will have one more element than the source one. You simply need to copy all the elements of the source array to the destination, and add your new element. Depends on different requirement of your post title & your post body, I added 2 solutions:
Solution 1
This solution add an element to your array AFTER sorting the array, as mentioned in the post title. But please notice that the element added is located at the tail of the new array.
Integer src[] = { 5, 4, 3, 2, 15, 8, 9 };
Integer dest[] = new Integer[src.length + 1];
Arrays.sort(src);
System.out.println(Arrays.toString(src));
// [2, 3, 4, 5, 8, 9, 15]
System.arraycopy(src, 0, dest, 0, src.length);
dest[src.length] = 6;
System.out.println(Arrays.toString(dest));
// [2, 3, 4, 5, 8, 9, 15, 6]
// ^
Solution 2
This solution add an element to your array BEFORE sorting the array. It contains the expected array as mentioned in your code comment in the post body.
Integer src[] = { 5, 4, 3, 2, 15, 8, 9 };
Integer dest[] = new Integer[src.length + 1];
System.arraycopy(src, 0, dest, 0, src.length);
dest[src.length] = 6;
Arrays.sort(dest);
System.out.println(Arrays.toString(dest));
// [2, 3, 4, 5, 6, 8, 9, 15]
// ^
See also:
Sorting methods in Arrays (Java Platform SE 8) - Oracle Help Center
System#arraycopy(Object, int, Object, int, int)

Collection with integer, need to increase and decrease it on itself

I have a task and I have some problems with it - hard to change a mindset i guess.
I need to create a collection, which keep integers and must perform such functions as:
Add and remove elements by its index and value (okay, i think it can be ArrayList or LinkedList, am I right?)
In case if element will be added other elements must be increased by a value of added element.
In case if element will be removed other elements must be decreased by a value of added element.
Last two functions..I have no clues how to make it. Probably some of you can show me a direction, where I need to move and what I need to do?
In my mind I need to create LinkedList (it allows me to remove elements by its index and value) and use some wrapped types for list. But how?
UPDATE
To clarify (from comments), this is the desired result of calling add() and remove():
add(1): [1]
add(2): [3, 2] // Existing values are incremented
add(3): [6, 5, 3]
add(4): [10, 9, 7, 4]
add(0): [10, 9, 7, 4, 0]
add(5): [15, 14, 12, 9, 5, 5]
remove(3): [15, 14, 12, 9, 5, 5] // Value not found, so no change
remove(9): [6, 5, 3, -4, -4] // All values are decremented
remove(5): [1, -2, -9, -9]
I would use an ArrayList. You can add elements in a specific index with
add(index, value)
You can remove elements by index with
remove(index)
For the second function, you can iterate the full ArrayList and add the value of the new element. After that, you add it to the ArrayList. For the third function you do it the opposite way: fist remove it and then you decrease its value to the remainig elements.
Last thing, remember you shouldn't (in fact I think you can't) remove an element of the ArrayList while you iterate it. So if you want to remove an element by its value, you can iterate the ArrayList keeping the indexes of the elements you want to remove, and then remove them. Hope it helps.
I think you need to get familiar with Java API Collection first, when you do that I'm pretty sure you will be able to resolve what you want.
I recommend this site: http://www.java2novice.com/java-collections-and-util
If I understood your question correctly, you don't need to change the elements in your collection to implement addition and subtraction (from all elements):
You could store in a variable (lets call it diff) the difference between the elements in the collection and the required result and update diff each time you add or remove an element.
Note that when you add an element, you probably have to alter the added element according to diff.
Example:
adding 1 to the array: [0], diff=1, array + diff: [1]
adding 2 to the array: [0, -1], diff=3 , array + diff: [3, 2]
adding 3 to the array: [0, -1, -3], diff=6, array + diff: [6, 5, 3]
removing 5 from array (actually removing 5-diff): [0, -3], diff=1, array + diff: [1,-2]
you can use ArrayList no need to use linkedlist in your use case
you need to iterate over the list and sum the integer with the existing values and add it to the list
you need to check if the list contains the Integer before removing it
you can try this code
public static void main(String[] args) throws Exception {
List<Integer> list = new ArrayList<>();
addAndSum(list, 1);
System.out.println(list);
addAndSum(list, 2);
System.out.println(list);
addAndSum(list, 3);
System.out.println(list);
addAndSum(list, 4);
System.out.println(list);
addAndSum(list, 0);
System.out.println(list);
addAndSum(list, 5);
System.out.println(list);
removeAndSustract(list, 3);
System.out.println(list);
removeAndSustract(list, 9);
System.out.println(list);
removeAndSustract(list, 5);
System.out.println(list);
}
private static void addAndSum(List<Integer> list, Integer i) {
for (int j = 0; j < list.size(); j++)
list.set(j, list.get(j) + i);
list.add(i);
}
private static void removeAndSustract(List<Integer> list, int i) {
if (list.contains(i)) {
list.remove((Integer) i);
for (int j = 0; j < list.size(); j++)
list.set(j, list.get(j) - i);
}
}
the output
[1]
[3, 2]
[6, 5, 3]
[10, 9, 7, 4]
[10, 9, 7, 4, 0]
[15, 14, 12, 9, 5, 5]
[15, 14, 12, 9, 5, 5]
[6, 5, 3, -4, -4]
[1, -2, -9, -9]

Passing a vector of integers to two separate functions but altered data gets passed to the other functions

*Update: Resolved did a deep copy, thanks for the help
I am using a vector of integers to simulate some sorting algorithms, when i insert numbers to the test vector and shuffle the order and pass it to a sorting function, if i pass the void sorting functions the same vector, when the vector gets sorted in a function previously passed the newly sorted vector gets passed to the function following it because it is already sorted i cannot show the sorting process. For example in my following code
#SuppressWarnings("unchecked") // Removes error given at when adding elems to int_vec
public static void CreateVec (int array_len)
{
Vector <Integer> int_vec = new Vector(array_len);
int temp_int = 1;
int low_bound = 0;
int high_bound = array_len - 1;
for(int i = 0; i<array_len; i++)
{
int_vec.addElement(temp_int);// creating a vec in respect to array len
temp_int ++;
}
Collections.shuffle(int_vec);
System.out.println("OG vec: " + int_vec); //original vector (random order)
BubbleSort(int_vec,array_len); //sending int_vec to bubble sort
InsertionSort(int_vec,array_len); // retrieves newly sorted vector sorted from BubbleSort (problem)
}
So my question follows, how can i keep sending my test vector (int_vec) with the randomly ordered elements rather than it keep sending the sorted vector to the other algorithms. Note i correctly implemented these algorithms, it works if i comment out the function calls to the other algorithm functions.
Create a copy of int_vec with new Vector<Integer>(int_vec) and pass in the copy to your sorting methods. This way, only the copy will get sorted, and int_vec will still be randomly ordered, and ready to be copied again for the next sorting method.
And yes, this is a shallow copy, but a deep copy is not needed here.
it doesnt seem to be working i did the following
Vector <Integer> int_vec = new Vector(array_len);
Vector <Integer> copy_bub = new Vector <Integer> (int_vec);
//...//
BubbleSort(int_vec,array_len);
InsertionSort(copy_bub,array_len);
and this is the output
Output:
OG vec: [4, 8, 9, 6, 10, 2, 1, 5, 3, 7]
Copy vec: [4, 8, 9, 6, 10, 2, 1, 5, 3, 7]
Bubble Vec: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Insertion Vec: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Insertion Vec: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Insertion Vec: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Insertion Vec: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Insertion Vec: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Insertion Vec: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Insertion Vec: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Insertion Vec: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Insertion Vec: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Insertion Vec: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Categories