Java: Comparing ArrayList item to User Input String - java

I have seen other threads on this, but I still don't understand the best approach. Issue is as started: One can't compare user input that is a String to an arrayList item (object). My List will be over 40 items.
So when I try to compare classesList.get(0) to the user input mage. It won't work.
List<String> classesList = new ArrayList<String>();
classesList.add("mage");
classesList.add("warrior");
classesList.add("thief");
Scanner input = new Scanner(System.in);
String input = input.next();
for (int counter = 0; counter < classesList.size(); counter++) {
if (input == classesList.get(counter)) {
//won't run body since can't compare
}
}
I found some who converted the arrayList to be a String. But I am unsure how I could then easily search through my list. I'd much rather leave it as a List instead. Is the best method to this approach?
String[] classesArray = classesList.toArray(new String[classesList.size()]);

I think you have to see if input string exist in the ArrayList, you have to use contains() method.
if(classesList.contains(input)) {
//Found in the arraylist.
}
But with you method, you can't compare strings using == operator. You should use equals() method for comparision
List<String> classesList = new ArrayList<String>();
classesList.add("mage");
classesList.add("warrior");
classesList.add("thief");
Scanner input = new Scanner(System.in);
String input = input.next();
boolean isExist = false;
for (String item : classesList) {
if (input.equals(classesList.get(counter))) {
//Your logic if it's there.
isExist = true;
break;
}
}
if(isExist) {
//Found in the arraylist.
}
Also if you want to make this comparision with ingnoring the case, you shoudl consider using equlasIgnoreCase() method instead of equals() method.

I don't fully understand your question, however you can test if a given String exists in the list using contains()
Some other pointers
Never compare Strings with ==, use .equals(). See this question
Iteration can be done more simply using (String element : list) syntax

Yes what you read is right, not to use following:
for (int counter = 0; counter < classesList.size(); counter++) {
if (input == classesList.get(counter)) {
//won't run body since can't compare
}
}
You cannot use == for comparison instead you should use equals method if you are using loop:
for (int counter = 0; counter < classesList.size(); counter++) {
if (input.equals(classesList.get(counter))) {
//won't run body since can't compare
}
}
Otherwise easier way is to use contains as mentioned in other answer.
Also see How do I compare strings in Java?
Cheers !!

You can use the contains method on your list to see if a particular string is contained inside of it, instead of iterating across it. However, the underlying list will still be iterating over the contents of the list internally.
What you could do instead, to improve speed, is to use a Set instead, which has a nice property of having contains be run in constant time.
Set<String> classesSet = new HashSet<>();
// none of your other code has to change, except for:
if(classesSet.contains(input)) {
// logic
}

Related

Returning Duplicates Arraylist

Below is a simple for loop I am using to try and go through and find the repeated ID's in a array list. The problem is that it only checks one index to the right so quite clearly if there is the same ID two, three or even four indexes across it will miss it and not report it as a repeated ID.
Obviously the goal of this code is to move through each index of the array list, get the ID and check if there are any other identical ID's.
Note for the below arraylist is...arraylist, the getId method simply returns the user ID for that array object.
for (int i=0; i<arraylist.size()-1; i++) {
if (arraylist.get(i).getId() == arraylist.get(i+1).getId()) {
System.out.println(arraylist.get(i).getId());
}
}
What I've tried and keep coming back to is to use two embedded for loops, one for iterating through the array list and one for iterating through an array with userIDs. What I planned on doing is checking if the current arraylist ID was the same as the array with 'pure' IDs and if it wasn't I would add it to the array of 'pure IDs. It would look something like this in psudocode.
for i<-0 i<arraylist size-1 i++
for j<-0 j<pureArray size j++
if arraylist.getId(i) != pureArray[j] then
increment pureArray size by one
add arraylist.getId(i) to pureArray
In practice perhaps due to my poor coding, this did not work.
So any opinions on how I can iterate completely through my arraylist then check and return if any the gotten IDs have multiple entries.
Thank you.
Looking at leifg's answer on this similar question, you can use two sets, one for duplicates and one for everything else, and you can Set#add(E), which "returns true if this set did not already contain the specified element," to determine whether or not the element is a duplicate. All you have to do is change the sets generics and what you are adding to them:
public Set<Integer> findDuplicates(List<MyObject> listContainingDuplicates)
{
// Assuming your ID is of type int
final Set<Integer> setToReturn = new HashSet();
final Set<Integer> set1 = new HashSet();
for (MyObject object : listContainingDuplicates)
{
if (!set1.add(object.getID()))
{
setToReturn.add(object.getID());
}
}
return setToReturn;
}
For the purpose of getting duplicates, nested for loop should do the job, see the code below. One more thing is what would you expect this nested for loop to do.
Regarding your pseudocode:
for i<-0 i<arraylist size i++
for j<-i+1 j<arraylist size j++
if arraylist.getId(i) != arraylist.getId(j) then
add arraylist.getId(i) to pureArray
1) Regarding j<- i+1, with every iteration you do not want to compare the same thing many times. With this set up you can make sure you compare first with others, then move to second and compare it to the rest (not including first because you already did this comparison) etc.
2) Incrementing your array every single iteration is highly impractical as you will need to remap and create a new array every single iteration. I would rather make sure array is big enough initially or use other data structure like another ArrayList or just string.
Here is a small demo of what I did, just a quick test, far no perfect.
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
// create a test array with ID strings
ArrayList test = new ArrayList<>();
test.add("123");
test.add("234");
test.add("123");
test.add("123");
String duplicates = "";
for(int i = 0; i < test.size(); i++) {
for(int j = i+1; j < test.size(); j++) {
// if values are equal AND current value is not already a part
// of duplicates string, then add it to duplicates string
if(test.get(i).equals(test.get(j)) && !duplicates.contains(test.get(j).toString())) {
duplicates += " " + test.get(j);
}
}
}
System.out.println(duplicates);
}
}
Purely for the purpose of finding duplicates, you can also create a HashSet and iteratively add the objects(ID's in your case)to the HashSet using .add( e) method.
Trick with HashSet is that it does not allow duplicate values and .add( e) method will return false if the same value is passed.
But be careful of what values(objects) you are giving to the .add() method, since it uses .equal() to compare whatever you're feeding it. It works if you pass Strings as a value.
But if you're giving it an Object make sure you override .equals() method in that object's class definition (because that's what .add() method will use to compare the objects)

Java Collection, Set, Map or Array to hold unique sorted non blank strings

I am fairly new to java and would like a container that I can use to hold strings that are not empty and have them sorted.
So far, I have mostly been using ArrayList, but this seems a bit limited for this case.
Thanks
Use TreeSet or TreeMap, depending on your requirements. Both are collections that accept unique elements and keep them sorted.
A Set is what you want, as the items in it have to be unique.
As the Strings should be sorted you'll need a TreeSet.
As for the non blank Strings you have to override the insertion methods like this:
Set<String> sortedSetOfStrings = new TreeSet<String>() {
#Override
public boolean add(String s) {
if(s.isEmpty())
return false;
return super.add(s);
}
};
EDIT: Simplified thanks to Peter Rader's comment.
Thanks for all the help. Here is what I eventually came up with, using TreeSet and apache commons StringUtils. My Input is a CSV String so, I didn't use the check on the input.
String csvString = "Cat,Dog, Ball, Hedge,, , Ball, Cat"
String[] array = StringUtils.split((String) csvString, ",");
for (int i = 0; i < array.length; i++)
{
array[i] = array[i].trim(); //Remove unwanted whitespace
}
set = new TreeSet<String>(Arrays.asList(array));
set.remove(""); //Remove the one empty string if it is there
set now contains: Ball,Cat,Dog,Hedge

trying to remove the first occurence of the number in the arraylist

public static void main(String [] args){
Scanner input = new Scanner(System.in);
System.out.println("Enter some numbers (all on one line, separated by spaces):");
String line = input.nextLine();
String[] numbers = line.split(" +");
ArrayList<Integer> a = new ArrayList<Integer>();
for(int i=0; i<numbers.length; i++)
a.add(new Integer(numbers[i]));
System.out.println("The numbers are stored in an ArrayList");
System.out.println("The ArrayList is "+a);
System.out.print("\nEnter a number: ");
int p = input.nextInt();
System.out.println(removeNumber(a,p));
System.out.println(removeNumber2(a,p));
}
public static <T> ArrayList<T> removeNumber(ArrayList<T> a, Integer e)
{
ArrayList<T> b = new ArrayList<T>();
for(int i = 0; i< a.size();i++)
{
if (a.get(i).equals(e))
a.remove(e);
}
return a;
}
if ex.value = 4, I want to remove 4 from the arrayList. If my arraylist contains [5,12,4,16,4], I want to remove the first occurence of four from it, and save it to another arraylist.
Don't want to use Iterators
Without using an iterator, here's what you could do to fix your code :
for(int i = 0; i< a.size();i++) {
if (a.get(i).equals(e.value)) {
a.remove(e.value);
i--;
}
}
Beyond the change of == to equals, you have to decrement i whenever you remove an element from the ArrayList. The reason for that is that removing the ith element from an ArrayList decreases the indices of all the elements that follow it by one. Therefore, the i+1th element will become the new ith element, so you must decrement i in order not to skip the next element.
EDIT : For some reason I was sure you wanted to remove all occurences of the number from the list, and not just the first one. If you only want to remove one element from the list, you don't have to worry about iterating over the rest of the list after removing that element.
You cannot iterate over an ArrayList and modify it at the same time, without an Iterator
Do like this :
for(Iterator<T> i = a.iterator(); i.hasNext();)
{
if (i.next().equals(e.value))
{
i.remove();
}
}
BTW, your b ArrayList is useless.
Along with the suggestion of using iterators, you should not be using the operator == which checks for reference equality. This will always be false in your scenario. You want to use the equals method instead which checks for value equality.
if (a.get(i).equals((Integer)e.value)))
You don't need to iterate through the list, either with an iterator or an index. ArrayList has a remove method that searches for and removes an element, and returns true or false depending on whether it found an element to remove. So you can say
while (true) {
boolean found = a.remove(e.value);
if (!found) {
break;
}
}
or
boolean found;
do {
found = a.remove(e.value);
} while(found);
or if you value compactness over readability,
do { } while(a.remove(e.value));
Note that a.remove(e), as you have in your original code, won't work at all. The ArrayList is an ArrayList of Integer, but e is an EX6. Thus, a.remove(e) won't find e in the list at all, since it isn't even the correct type. It should compile fine, since remove is defined to allow any Object as a parameter, but it will never find anything (since the equals method of Integer always returns false for a non-Integer).

Java ArrayList not working on characters in my case

I have a big doubt. I want to find the first char of a string here which isn't repeated.For e.g. for the input below should return 'c'. So this is how I was planning on doing it. But I noticed the remove method is looking to remove at an index of 98 vs removing the object "a". How do I force it to remove the object "a" instead of removing from index ?
Why doesn't this work ?
And what can I do to change this ?
Is ArrayList always guaranteed to store things in order ?
public void findStartingLetter()
{
String[] array={"a","b","c","d","b","a","d","d","d"};
List<Character> list = new ArrayList<Character>();
for(String i:array)
{
if(list.contains(i.charAt(0)))
list.remove(i.charAt(0));
else
list.add(i.charAt(0));
}
}
EDIT:
Performance wise is this an O(n) function ?
You have to cast manually to a Character since the char gets casted to an int, which in turn goes by index and not value.
list.remove((Character) i.charAt(0));
Will ensure that it is done properly.
Is ArrayList always guaranteed to store things in order ?
Depends on your definition of order:
If you mean the order you add them, Yes.
If you mean numerical/alphabetical order, then No, but you can sort it by using
Collections.sort(list)
This will sort by the natural ascending order of the objects in the list.
I'm not entirely sure why you want to use a List for this, but I would instead recommend a Set - it's guaranteed to not contain duplicates.
Here's the first approach, with a set:
public Set<Character> addToSet(String[] elements) {
Set<Character> res = new HashSet<>();
for(String c : elements) {
res.add(c.charAt(0));
}
return res;
}
Now, if you really want to do this with a List, then it's similar code - you just need to check to see if the element exists before you add it in.
public List<Character> addUnique(String[] elements) {
List<Character> res = new ArrayList<>();
for(String item : elements) {
Character c = item.charAt(0);
if(!res.contains(c)) {
res.add(c);
}
}
return res;
}
Your approach to this problem is quite confusing and you ask many questions which do not seem to relate to your problem.
Why not just use:
String testString = "abcdbaddd";
Character retVal = null;
for (int i = 0; i < testString.length() -1; i++) {
if (testString.charAt(i) == testString.charAt(i + 1)) {
retVal = testString.charAt(i);
break;
}
}
return retVal;
That gets you the first non-repeated character (I'm assuming that by repeated you mean repeated and adjacent) or null if no such character exists.

Java - Checking if an ArrayList of String are in alphabetical order

I have an ArrayList called account which contains Strings. I'm trying to write a method that checks if they are in order and returns true or false based on whether they are in order or not.
How would you go about this? I've already tried checking the initial chracter with a for-loop but it went terribly wrong. I created a new ArrayList and set it equal to the original, then sorted it and compared them but since they contained the same data it always came back true.
Just an extra quick question, since I'm doing this for Strings, how would you check if some numbers were in ascending/descending order? Throught the same principal?
Thankyou!
Try this (assuming you want to compare the strings using their natural ordering, of course):
String previous = ""; // empty string: guaranteed to be less than or equal to any other
for (final String current: thelist) {
if (current.compareTo(previous) < 0)
return false;
previous = current;
}
return true;
This is due to the fact that String implements Comparable<String>, and the comparison will be done using the strings' natural ordering.
If you don't mind using external library (Guava) Ordering will do:
boolean isSorted = Ordering.natural().isOrdered(list);
This will do for String and other Comparables. If you are check ordering of some custom type, use any of the static factory methods in the Ordering class or subclass it.
Edit for case-insensitive ordering use:
boolean isSorted = Ordering.from(String.CASE_INSENSITIVE_ORDER).isOrdered(list);
I think a for loop would be suitable for this. The approach I would take would be to check each word against the previous and see if they are in the correct alphabetical ordering. Best case this is O(2) for determining that the list is out of order, worst case O(n) for telling you that the list is in order.
Edit: fge's answer above outlines the code for approach described.
Use the sort method of Collection class :
List<String> list = new ArrayList<String>();
//Add Elements
Collections.sort(list);
Sorts the specified list into ascending order, according to the
natural ordering of its elements.
ArrayList<String> initial = // smth
ArrayList<String> copy = // copy initial list here
Collections.sort(initial);
return initial.equals(copy);
Just use a loop and check if they are in order:
boolean isSorted = true;
for(int i = 0; i < list.size() - 1; i++) {
// current String is > than the next one (if there are equal list is still sorted)
if(list.get(i).compareToIgnoreCase(list.get(i + 1)) > 0) {
isSorted = false;
break;
}
}

Categories

Resources