Infinite Loop Java for an unfathomable reason - java

The code is supposed to partition the list into sets. If the ArrayList contains the same strings twice in a row, it will add their indexes to one HashSet otherwise the indexes will be in different HashSets. The point is to put the indexes of all the same strings from the ArrayList in the same HashSet and the indexes of the different strings in different HashSets. For example, the program SHOULD print [[0, 1][2, 3]] but it's stuck in an infinite loop. I put a print statement to verify whether the first two indexes are being added to the HashSet, which they are. The program prints [[0, 1]] instead of the expected result. For some reason, list.get(index1).equals(list.get(index2)) always evaluates to true even though I update the indexes in the loop and the result should be false at the second iteration.
package quiz;
import java.util.HashSet;
import java.util.ArrayList;
import java.util.Iterator;
public class Question {
public static void main(String[] args) {
Question q = new Question();
ArrayList<String> list2 = new ArrayList<String>();
list2.add("a");
list2.add("a");
list2.add("c");
list2.add("c");
System.out.println(q.answer(list2));
}
public HashSet<HashSet<Integer>> answer(ArrayList<String> list){
HashSet<HashSet<Integer>> hashSet = new HashSet<HashSet<Integer>>();
HashSet<Integer> set = new HashSet<Integer>();
Iterator<String> it = list.iterator();
int index1 = 0;
int index2 = 1;
while (it.hasNext()){
while (list.get(index1).equals(list.get(index2))){
set.add(index1);
set.add(index2);
if (index1<list.size()-2){
index1=index1+1;
index2=index2+1;
}
}
hashSet.add(set);
System.out.println(hashSet);
}
/*else{
set.add(i);
}*/
return hashSet;
}
}

You get an infinite loop because you are using the iterator hasNext() but not using the it.next() afterwards which move the index forward.
In addition, you do not really need the iterator because you are not using the values. You should do something like that:
while(shouldStop)
......
if (index1<list.size()-2){
index1=index1+1;
index2=index2+1;
} else {
shouldStop=true
}
........

Related

remove duplicate value using collection framework

I am trying to remove duplicate values by converting an array to an arraylist and then further converting the arraylist to a Hashset. As we know hashsets do not contain any duplicate values. But i am not getting any output. I am implementing this technique because I want to avoid using a for loop .
import java.util.*;
public class RemoveDupliucate {
public static void main(String[] args) {
int a[]= {1,2,1,3,2,15,4,6,4};
List l=Arrays.asList();
TreeSet<Integer> m=new TreeSet(l);
for(Integer i:m)
{
System.out.print(i);
}
}
i am not getting any output.
If you want to remove duplicate elements from an array, there is already a method using java 8 stream,
Arrays.stream('array').distinct().toArray();
Which will remove all the duplicate elements and return the array.
for your code,
int a[]= {1,2,1,3,2,15,4,6,4};
a = Arrays.stream(a).distinct().toArray();
this should work, if you want to remove duplicates.
This line will create an empty list, that’s why you got no output:
List l = Arrays.asList();
It should be something like
List<Integer> l = Arrays.asList(1,2,1,3,2,15,4,6,4);
It is very easy in Java 8 streams
int array[]= {1,2,1,3,2,15,4,6,4};
//Use Java 8 Streams to get distinct values from an array
int[] unique = Arrays.stream(array).distinct().toArray();
If you don't want to use Java 8 streams API you can try in below
Converting array into set
public void printDistinctElements(int[] inputArray)
{
Set<Integer> elementSet = new HashSet<Integer>();
for(int i = 0; i<inputArray.length; i++)
{
elementSet.add(inputArray[i]);
}
System.out.println("Distinct Elements");
for (int i : elementSet) {
System.out.print(" " +i);
}
}

Why is this particular code for comparing arraylists not working?

I have two different arraylists that I want to compare - specifically to check if a certain element of list1 exists in list2.
This is my code:
for (int i = 0; i < list1.size(); i++){
if (list2.contains(list1.get(i))) {
System.out.println ("match");
}
}
Basically I am looping through list1 - and checking if list2 contains element from list1. This if statement is however not being executed - and no values are null.
The logic and code seems OK to me. What is wrong?
If you're trying to find the intersection between two lists, the better approach would be to use retainAll method. Suppose you have two lists such that:
List<String> list1 = asList("Martin", "Eric", "Kent");
List<String> list2 = asList("Kent", "Josh", "Eric");
The following list will hold the intersection between the two:
List<String> intersection = new ArrayList<>(list1);
intersection.retainAll(list2);
After calling retainsAll, intersection will only contains Kent and Eric.
(This is really a comment. Unfortunately, SE has a coincidental coupling between comment vs. answer and formatting options.)
Here is an example of a complete program that tests your code, but works. For clarity, I printed a non-empty string on match. I suggest modifying it by replacing the lists with the failing case. If it fails, post the complete program.
import java.util.Arrays;
import java.util.List;
public class Test {
public static void main(String[] args) {
List<String> listA = Arrays.asList(new String[] { "job" });
List<String> listB = Arrays.asList(new String[] { "bbb", "job" });
System.out.println("One match");
matcher(listA, listB);
}
public static void matcher(List<String> list1, List<String> list2) {
for (int i = 0; i < list1.size(); i++) {
if (list2.contains(list1.get(i))) {
System.out.println("Found one.");
}
}
}
}

ArrayList method "lastIndexOf" returning -1 when item does exist in ArrayList

I'm trying to get the basics of ArrayLists, but I can't get the lastIndexOf method to work properly. As you can see in my code below, the program runs and should print "1", the index of the number 3, but prints "-1" instead (which should be printed only if 3 didn't exist in the ArrayList). What's my problem?
import java.util.ArrayList;
public class Pile {
public static void main(String[] args)
{
int[] myArray = {1,3,23,4};
ArrayList<Integer> myList = new ArrayList<Integer>();
for (int i=0;i<myArray.length;i++) {
myList.add(myArray[0]);
}
System.out.println(myList.lastIndexOf(3));
}
}
You're only adding the first element of myArray to myList
You should replace
myList.add(myArray[0]);
with this
myList.add(myArray[i]);
Also, instead of manually copying the elements, you could use Arrays#asList (but you would need to change the type of myArray to Integer[]):
List<Integer> myList = Arrays.asList(myArray);
You are only adding the first element of the array multiple times to the list.
myList.add(myArray[0]);
That's why your list doesn't contain 3.
Change it to
myList.add(myArray[i]);

Find the duplicate number in an array

I am trying to find the duplicate number in an array, but it's not working.
public class FindDuplicateNumber {
/**
* #param args
*/
public static void main(String[] args) {
int[] arr={10,20,30,40,40,25};
int[] duplicate=duplicateNumber(arr);
for(int dup : duplicate ){
System.out.println("duplicate elements are:\t"+ dup);
}
}
public static int[] duplicateNumber(int[] arr){
int[] duplicate = new int[arr.length];
for(int i=0;i<=arr.length-1;i++){
if(arr[i]==arr[++i]){
duplicate[i]= arr[i];
}
}
return duplicate;
}
}
Never use ++i or i++ inside a loop unless you really want to skip one of the array (or similar) elements over which you are iterating.
This
if(arr[i]==arr[++i]){
is not the same as
if(arr[i]==arr[i+1]){
That said, never use ++i or i++ within an expression where also i occurs.
Later
Another problem you'll soon see is that the array for holding the duplicates is too long. For this, a List is more appropriate.
Why it does not work
The additional increment makes the loop skip every other element, so the pair of adjacent values 40 is never compared.
There are a few problems with the algorithm you're using right now.
You're using arr[++i] inside of your for loop. Are you aware of what this does? It increments i by 1, which your for loop already does. Hence the i++ at the end. Therefore as you run through your for loop, you are incrementing I twice and skipping half of your array values.
You are looping through the array and comparing one value, arr[i], to (I'm assuming what you were trying to do is compare it to the next value, arr[i+1]. Do you see why this wouldn't work, unless the array was sorted? What you need to do is compare each value to every other value in the array which is going to require 2 for loops.
I don't want to just write this code for you because I feel like with these hints you can figure it out. If you need any more help, let me know.
What you are attempting is not reasonable to do with primitive arrays. One reason is that you do not know in advance how large your duplicates array should be. This type of problem needs to use an array type that is modifiable, such as ArrayList. Here is a simple version using ArrayList and HashSet.
The .add() method for a HashSet returns false if the number has already been added.
import java.util.HashSet;
import java.util.ArrayList;
import java.util.List;
public class FindDuplicateNumber {
/**
* #param args
*/
public static void main(String[] args) {
int[] arr={10,20,30,40,40,25};
for(Integer dup : duplicateNumber(arr)){
System.out.println("duplicate elements are:\t"+ dup);
}
}
public static List<Integer> duplicateNumber(int[] arr){
HashSet<Integer> set = new HashSet<Integer>();
List<Integer> duplicates = new ArrayList<Integer>();
for (int index = 0; index < arr.length; index++)
if (!set.add(arr[index])) // false if already in set.
duplicates.add(arr[index]);
return duplicates;
}
}

Remove List<String> duplicates using equals

I'm fairly new to Java and I've been trying to solve the following problem unsuccessfully.
Write a Java method that will remove duplicates from a given list.
Assuming:
Method accepts type List
Return type is void
Duplicates are determined using equals()
Main:
Creates an instant of List and loads it with duplicate String values
Invoke removeDuplicates(), pass in this list
Outputs modified list to the console.
I can solve the problem by passing in my list to a new HashSet and copy it back.
But the problem is:
Question is asking me to solve it using equals()...
If the return type is void, how can i output it in the main ?
import java.util.*;
public class Question1 {
public static void main(String[] args) {
String[] words = {"good","better", "best", "best", "first" , "last", "last", "last", "good"};
List<String> list = new ArrayList<String>();
for (String s : words) {
list.add(s);
}
removeDuplicates(list);
}
static void removeDuplicates(List<String> array){
HashSet<String> hs = new HashSet<>();
hs.addAll(array);
array.clear();
array.addAll(hs);
for (String x : array){
System.out.println(x);
}
}
}
EDIT: well, this one works, but as you can see i'm not using equals() and i'm printing out from my static method, not from main.
Also, is there any way I can populate the List faster than using String[] ?
java.util.HashSet uses Object.equals(Object) in its implementation of Set.add(Object) to determine that the element being inserted is unique (as defined by not being equal to another element). HashSet also has the advantage of allowing you to do the de-duping process in O(n) time vs a more naive approach of comparing every element to every other element in O(n^2) time.
The code in main will see the modified list, because the List object is mutable. When a method changes the state of a passed in argument the calling code will see those changes.
removeDuplicates creates a set, then iterates over the input list. If it encounters an element in the input list, that is also in the set, removeDuplicates removes the element from the input list, otherwise it adds the element to the set.
Java is a call-by-reference language (sort of). This means, the method removeDuplicates can modify the List<String> array that it receives and the caller will see that modified list after the call to removeDuplicates returned.
Here's how you would do the same thing without using a Set and just using equals() (also to somewhat answer your "EDIT" question about initializing a List) :
public static void main(String[] args) {
List<String> list = new ArrayList<String>(Arrays.asList(new String[] {
"good", "better", "best", "best", "first", "last", "last", "last",
"good"}));
removeDuplicates(list);
for (String x : list) {
System.out.println(x);
}
}
static void removeDuplicates(List<String> array) {
for (int i = 0; i < array.size(); i++) {
String next = array.get(i);
// check if this has already appeared before
for (int j = 0; j < i; j++) {
// if it has, stop the search and remove it
if (next.equals(array.get(j))) {
array.remove(i);
// decrement i since we just removed the i'th element
i--;
// stop the search
break;
}
}
}
}
That said, using HashSet is a better idea since as has already been pointed out it is more efficient.
If you want the efficiency of HashSet but still preserve the order of the List you could do something like this :
static void removeDuplicates(List<String> array) {
Set<String> set = new HashSet<String>();
for (int i = 0; i < array.size(); i++) {
String next = array.get(i);
// check if this has already appeared before
if (!set.add(next)) {
// if it has then remove it
array.remove(i);
// decrement i since we just removed the i'th element
i--;
}
}
}
The probably easiest way would be to use a Set in the first place, which by definition does not allow duplicates.
For your actual problem, you can do several approaches:
The easy but slow approach: compare each element A with each other element N in the list. If A.equals(N) remove N. Hint: you only need to compare A to each further element, as you have already checked each element before A.
The faster approach: sort the list using the natural comperator. Now you no longer need to compare each element A vs N, but only A vs the next few elements. To be exact: until you find the first element that is not equal to A. In this case you can assume that there is no further duplicate of A (thanks to the sorting) and continue with this next element as A.
The Map approach (fast but takes more memory): for each element put into the list, put the same element into a Map with any Object as value. Now you can just look-up whether or not that element is already in the map, and if it is, it is a duplicate.
The best way would be the 2nd approach as the sorting is very fast, you only need to get each element once, and there is no 2nd list necessary.
Edit: The 2nd approach in code:
static void removeDuplicates(List<String> array) {
if (array.size() <= 1) {
return;
}
Collections.sort(array);
final Iterator<String> it = array.iterator();
String a = it.next(), n;
while (it.hasNext()) {
n = it.next();
if (((a == null) && (n != null))
|| ((a != null) && (a.equals(n) == false))) {
a = n;
} else {
it.remove();
}
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("good");
list.add("better");
list.add("best");
list.add("best");
list.add("first");
list.add("last");
list.add("last");
list.add("last");
list.add("good");
removeDuplicates(list);
System.out.println(list.toString());
}
public static void removeDuplicates(List<String> list) {
if (list != null) {
for (int i = 0; i < list.size(); i++) {
ListIterator<String> listIterator = list.listIterator();
while (listIterator.hasNext()) {
int nextIndex = listIterator.nextIndex();
String nextElement = listIterator.next();
if (list.get(i).equals(nextElement) && i != nextIndex)
listIterator.remove();
}
}
}
}
}

Categories

Resources