Java set iteration in range - java

I want to iterate over java set by providing some range. like I can do it for list..
//for list
int startRange=3;
int endRange = 5;
List list = myList();
for (int i=startRange;i<endRange;i++){
System.out.println(list.get(i));
}
Now I wanted to iterate on below java set like above in startRange and endRange
Set<String> set = new java.util.HashSet<String>(list);
Thanks.

int count =0, min= 3 , max = 5;
Set<String> s = new HashSet<String>();
Iterator<String> itr = s.iterator();
while (itr.hasNext()) {
if ( count > min && count < max ) {
//Do something
}
count++;
}

You can use a LinkedHashSet and maintain the order.

See my comment below.
#alfasin is correct; List encompasses a total ordering on its elements, but HashSet has no such thing... PS you should use List.listIterator in your original code.
That being said, there is something similar for other kinds of Sets that do impose a total order -- SortedSets. There exists an analogous subSet, as well as headSet and tailSet which have similar functions. These also exist in NavigableSet along with other methods like ceiling, floor, etc.
Note that the orders here are not that much alike. List order is essentially arbitrary, whatever the user intended, while SortedSets order using a comparison sort.

Set is not ordered use Class LinkedHashSet

//You can change the Set to Array and then iterate over a range.
Set<Integer> set = new TreeSet<Integer>();
for (int i = 0; i <= 100; i++) {
set.add(i);
}
Object[] array = set.toArray();
for (Integer i = 0; i < 100; i++) {
System.out.print(array[i] + " ,");
}

Related

HashSet not returning expected output

I want to store unique lists, so I am using HashSet. But, I am not getting desired output. Here is my code, Could you tell me what is going wrong?
public List<List<Integer>> threeSum(int[] nums) {
Set<List<Integer>> res = new HashSet<>();
for(int i = 0; i< nums.length; i++){
int target = 0-nums[i];
Set<Integer> neg = new HashSet<>();
for(int j = i+1 ; j<nums.length; j++){
int rem = target - nums[j];
if(neg.contains(nums[j])){
res.add(new ArrayList<>(Arrays.asList(nums[i], rem, nums[j])));
}
else{
neg.add(rem);
}
}
}
System.out.println(res);
return new ArrayList<>(res);
}
Here my nums is [-1,0,1,2,-1,-4].
My output is [[-1,2,-1],[0,1,-1],[-1,0,1]]. Why am I getting both [0,1,-1] and [-1,0,1] into res as both contain the same elements. I what only one of these? What should I do?
From the Javadoc of List.equals:
Returns true if and only if the specified object is also a list, both lists have the same size, and all corresponding pairs of elements in the two lists are equal.
So, [0,1,-1] and [-1,0,1] aren't equal, despite containing the same elements, because they aren't in the same order.
The easiest way to solve this would be to sort the list:
res.add(Stream.of(nums[i], rem, nums[j]).sorted().collect(toList()));
You can sort the List before adding to the Set so they will be in the same order.

Removing contiguous duplicates in ArrayList [Java]

I am doing a simple Java program and I need to remove all of the contiguous duplicates in a String ArrayList.
My String ArrayList is something like this:
list = [a,b,c,c,d,a,b,c,d]
My goal is removing all (and only!) the contiguous duplicates so that the result would be: [a,b,c,d,a,b,c,d]. As you can see, one of the two contiguous "c" has been removed.
I tried something like this:
for (int i = 0; i<list.size(); i++) {
if (list.get(i).compareTo(list.get(i+1))==0) {
positionToRemove.add(i);
}
}
Where positionToRemove will at the end contain all the position of the contiguous elements which I will then remove using list.remove() (still not done)
Unfortunately I get
java.lang.IndexOutOfBoundsException
I am quite positive there is a very simple way to achieve this but I can't remember it at the moment!
There is no need to store the indexes of the elements you need to remove. Just remove it directly by:
int size = list.size();
for (int i = size - 1; i >= 1; i--) {
if (list.get(i).compareTo(list.get(i - 1)) == 0) {
list.remove(i);
}
}
In the last iteration of the for loop, list.get(i+1) goes beyond the bounds of the list and thus the IndexOutOfBoundsException. In any array/arraylist, the maximum accessible index is always size/length - 1.
To fix that you need to change your logic a bit.
for (int i = 1; i<list.size(); i++) {
if (list.get(i-1).compareTo(list.get(i))==0) {
positionToRemove.add(i);
}
}
When you access the List using index + 1 or i+1, you overstep the bounds of the List on the last iteration. You can fix this by setting the conditional for your for loop to i < list.size() -1.
for (int i = 0; i < list.size() -1; i++) {
if (list.get(i).compareTo(list.get(i+1))==0) {
positionToRemove.add(i);
}
}
It should not reach the length of your list. You must shutdown the traverses at size -1.
for (int i = 0; i<list.size() - 1; i++) {
if (list.get(i).compareTo(list.get(i+1))==0) {
positionToRemove.add(i);
}
}
Where positionToRemove will at the end contain all the position of the
contiguous elements which I will then remove using list.remove()
(still not done)
Instead of storing each position, you could start from the end of the list and directly remove the current element if it's the same as its left neighbour. Using this, you don't need to create another list containing the indexes of the objects you want to remove.
List<String> list = new ArrayList<>(Arrays.asList("a","b","c","c","d","a","b","c","d"));
for(int i = list.size() - 1; i > 0; i--){
if(list.get(i).compareTo(list.get(i-1)) == 0){
list.remove(i);
}
}
System.out.println(list);
Which outputs:
[a, b, c, d, a, b, c, d]
You can do this with Java 7, using iterator.
Iterator<Integer> iterator = collection.values().iterator();
Integer previousValue = null;
while(iterator.hasNext()) {
Integer currentValue = iterator.next();
if(currentValue.equals(previousValue)){
iterator.remove();
}
previousValue = currentValue;
}

Getting n random elements in array

I want to get n unique random elements from my array.
For example:
if n = 4;
I want to randomly get
array[0], array[3], array[7], array[2]
The problem is getting a random integer will lead to collisions easily (psuedocode):
for n times
{
r = generateRandomInteger within n-1
list.push(array[r]); //array[r] can be the same.
}
collisions abound, especially on small arrays.
What's a particularly elegant way to solve this?
You can use a Set instead of a List which will eliminate the duplicates. Accordingly you'll need to change your loop condition as well. Something like this
while set.size() is less than n
{
r = generateRandomInteger within n-1
set.add(array[r]); //if its the same, it won't be added to the set and the size won't increase
}
You can do this two way : i suggest you to use first one .
First by using SET :
for n times
{
r = generateRandomInteger within n-1
// you can use SET instead of LIST cause SET not allow duplication.
set.push(array[r]); //array[r] can be the same.
}
Second by using LIST :
for n times
{
r = generateRandomInteger within n-1
if(!list.contains(array[r]))
list.push(array[r]); //array[r] can be the same.
}
You can add all random ints to a list and generate a new random, till the list doesnt contains this random int. Thats not the best performance, but it works.
List<Integer> randoms = new ArrayList<Integer>()
for(int i=0; i<n;i++){
while(randoms.contains(r)) {
r = Random.nextInt(array.length-1);
}
randoms.add(r);
list.push(array[r]);
}
Using a Set is probably the best thing to do.
If you want unique elements from array (i.e. the values of array[]) then use R.J's solution. If you want unique indices:
while set.size() is less than n
{
r = generateRandomInteger within n-1
set.add(r);
}
foreach(r: set)
{
list.add(array[r]);
}
Be carefull if you want more elements then the length of the array, since you will get an infinite loop:
if(n>array.length)
{
print("Cannot get more then ... elements!");
return null;
}
int n = 4;
for (int i = 0; i < n; i++)
{
int index = RandomBetweenInclusive(i, array.length() - 1); //made up function
int temp = array[i];
array[i] = array[index];
array[index] = array[i];
}
//array values between indices 0 and n-1 will be random and unique values of array
What I usually do in this scenario is push all the items I want to select-from into a collection
var selectFrom = original.clone; // or build array
var selected = new collection;
Then I go about removing random elements in the selectFrom collection
for (i = 0; i < toSelect; i++)
{
var rndItem = selectFrom[ rand() * selectFrom.length ];
selected.add(rndItem);
selectFrom.remove(rndItem);
}
This way I select randomly from what remains and do not have to worry about clashes in random numbers / indexs.

Removing Integer from Arraylist

I'm trying to rid of duplicates for my Bingo Program so I created an ArrayList and I want to remove the integer that is printed out in the loop. I think the loop I'm using is wrong but I'm not sure.
List<Integer> list = new ArrayList<Integer>();
for(int i = 1; i <= 75; i++){
list.add(i);
}
for (Integer s : list) {
Collections.shuffle(list);
System.out.println(s);
list.remove(//);
}
Do like this.
for (Iterator<Integer> iterator = list.iterator(); iterator.hasNext();) {
Integer s = iterator.next();
System.out.println(s);
iterator.remove();
}
If you're removing all the integers, it would be a lot easier to just do this:
Collections.shuffle(list);
for (Integer s : list) {
System.out.println(s);
}
list = new ArrayList<Integer>();
Or, if you really want to keep the same list instance:
Collections.shuffle(list);
for (Integer s : list) {
System.out.println(s);
}
list.clear();
Just creating a new array list is more efficient because it allows the garbage collector to just collect the entire old list, rather than removing the entries one by one. If you have multiple references to the same instance, however, then you'd need to actually clear the list instead.
Also note that the shuffle call has been moved outside the loop. Once you've done one shuffle, the list is already randomized, so shuffling again is kind of pointless... If you really want a "better" shuffle, you could do something like call shuffle 7 times before the first loop.
I would suggest using a HashSet<Integer> which doesn't allow duplicates:
Set<Integer> set = new HashSet<Integer>();
Are you sure this is not what you need?
private static final int NUM_BALLS = 75;
List<Integer> list = new ArrayList<Integer>();
for(int i = 1; i <= NUM_BALLS; i++){
list.add(i);
}
Collections.shuffle(list);
while (!list.isEmpty()) {
Integer s = list.remove(list.size() - 1); // for better performance as noted by #Holger
System.out.println(s);
}
use following code
Random generate = new Random();
Set<Integer> set = new HashSet<Integer>();
for(int i = 1; i <= 75; i++){
set.add(generate.nextInt(75));
}
Iterator<Integer> iterator = set.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
iterator.remove();
}
System.out.print(set.size());

Why does my output of randomly selected numbers contain duplicates?

My code needs to randomly select 6 numbers from a list ranging from 1 to 45.
Once when I ran my code (below) the output was [4, 4, 17, 18, 27, 37]. I was not expecting any duplicates in the output. How is it possible that there are duplicates? My code should be removing numbers from list as they are selected.
Random rng = new Random();
int size = 45;
int sixList[] = new int[6];
ArrayList<Integer> list = new ArrayList<Integer>(size);
ArrayList<Integer> list2 = new ArrayList<Integer>(6);
for(int i = 1; i <= size; i++) {
list.add(i);
}
Random rand = new Random();
for(int i = 0; list.size() > 39; i++){
int index = rand.nextInt(list.size());
if (index == 0){
index = rand.nextInt(list.size());
list2.add(index);
list.remove(index);
}else{
list2.add(index);
list.remove(index);
}
}
Collections.sort(list2);
System.out.print(list2);
The problem is that you are adding the index value to your list of random numbers.
Change your code
list2.add(index);
list.remove(index);
To
list2.add(list.remove(index));
List maintain index and does not care about duplicate elements at all. To avoid duplicates you must use Set rather than List. If you have any user-defined class going in the Set, then dont forget to implement equals() and hashcode() which are used to determine if elements are duplicate or not by the Set classes like HashSet.
If you have primitives going in you Set, then forget about duplicates as duplicates will be automatically handled for primitive data-types like int,long etc. So I suggest you to use Set rather than List. to avoid duplicate elements in the collection

Categories