I want to delete specified data in an arraylist from another class based on what the user input
so when the user input Rice, the data with 'Rice' in it will be deleted
this is the code so far
the data is stored in ArrayList rm in a subclass named RegularMenu.
ArrayList<RegularMenu> rm = new ArrayList<RegularMenu>();
Quiz1(){
int input;
do{
System.out.println("1. Add Regular Menu");
System.out.println("2. Add Special Menu");
System.out.println("3. Show All Menu");
System.out.println("4. Delete Regular Menu");
System.out.println("5. Delete Special Menu");
System.out.println("6. Exit" + "\n");
System.out.print("Choice [1-6] ");
Scanner s = new Scanner(System.in);
input = s.nextInt();
if (input == 1 ){
String code, name;
int price;
System.out.println("Add Regular Menu");
System.out.print("Input Menu Code [R...]: ");
s.nextLine();
code = s.nextLine();
System.out.print("Input Menu Name [5-20]: ");
name = s.nextLine();
System.out.print("Input Menu Price [10000-130000]: ");
price = s.nextInt();
rm.add(new RegularMenu(code, name, price));
}
else if (input == 2){
}
else if (input == 3){
}
else if (input == 4){
System.out.println("Input menu code you want to delete");
String a = s.nextLine();
for(int i=0;i<rm.size();i++){
if(a == rm.get(i).getCode()){
String code = rm.get(i).getCode();
a = code;
rm.remove(a);
}
}
}
else if (input == 5){
}
}while(input != 6);
}
i can add the data, but when try to remove it, the error occurred.
Let me know if I'm not clear enough.
The problem is that you are using List.remove(Object) wrong instead of List.remove(int).
List.remove(Object)
boolean remove(Object o)
Removes the first occurrence of the specified element from this list, if it is present (optional operation). [...] More formally, removes the element with the lowest index i such that (o==null ? get(i)==null : o.equals(get(i))) [...]
Trying to remove a RegularMenu with a String instance won't work because a String instance can't compare itself with a RegularMenu, so it will never be equivalent. (It will use String.equals(RegularMenu) method to find where is the instance to remove.
If you want to use List.remove(Object), pass the instance itself :
rm.remove(rm.get(i));
Note:
that this will remove the first occurrence only, so if you have two "equivalent" instances, only the first one will be removed.
List.remove(Object) will search for the index where the instance passed is using Object.equals to remove by index. But in your case you already did the job with if(a == rm.get(i).getCode()) (incorrectly, see "String comparison"),
List.remove(int)
E remove(int index)
Removes the element at the specified position in this list (optional operation). Shifts any subsequent elements to the left (subtracts one from their indices) [...]
Since you know the index, you can use rm.remove(i) (List.remove(int)) to remove the value at the current index.
Careful with the index that way, the right part of the list with shift on the left. See Lajos Arpad's answer for more information
Iterator
Another solution to remove items from an ArrayList is to use the iterator. You get the Iterator and iterate every items in it. Then if one match you call Iterator.remove to remove properly the item. You can even stop the loop if you only want to remove one item
Sample data :
List<String> datas = new ArrayList<>();
datas.add("foo");
datas.add("bar");
datas.add("bar");
datas.add("foo");
datas.add("bar");
datas.add("bar");
Code :
Iterator<String> it = datas.iterator();
String s;
while(it.hasNext()){
s = it.next();
if("foo".equals(s)){
it.remove();
}
}
System.out.println(datas);
[bar, bar, bar, bar]
I precise using ArrayList because some Collection don't implements the method remove for the Iterator giving an Exception.
Predicate - removeIf
Since Java 8, Collection.removeIf exists and allows you to do a quicker solution (using the same sample data) :
final String a = "foo";
datas.removeIf(s -> a.equals(s));
System.out.println(datas);
[bar, bar, bar, bar]
It will iterate and check for each instance of RegularMenu in it if the Predicate passed will be true, if so, the item will be removed.
String comparison
Also, note the comparison "foo".equals(s) instead of "foo" == s.
More information in How do I compare strings in Java?
You can iterate your array list with a loop and remove all matches:
for (int i = 0; i < yourArrayList.size(); i ++) {
if(a.equals(rm.get(i).getCode())){
yourArrayList.remove(i--);
}
}
Your mistake was that you tried to remove a from the ArrayList using remove, but remove expects an int, representing the index to be removed. In my code notice that I am decrementing i after removing to be able to remove consequent matches.
You can remove elements from List by index
for(int i=rm.size()-1; i>=0; i--) {
// you are deleting elements from the list while iterating,
// thus it is better to iterate backwards (rm.size()..0):
if(a.trim().equals(rm.get(i).getCode().trim())) {
rm.remove(i);
}
}
Note: when you delete an element under index i, all elements to the right (i+1, ...) will be moved to the left for one position.
Thus, when iterating from left to right and deleting elements, you will be messing with indices.
On the other hand, when you are iterating from right to left and deleting something at position i, all elements to to right will still be moved one position to the left, but It does not matter for you, because you will not iterate on them.
aaaaBcccc -> aaaacccc
^ ^ ^ ^
0.. i 0.. i
for(int i=0;i<rm.size();i++) {
if(a.trim().equals(rm.get(i).getCode())) {
rm.remove(i);
break;
}
}
In the list, you can remove elements by using index.
Find below code :
for(RegularMenu regularMenu:rm){
if(a.equalsIgnoreCase(regularMenu.getCode())){
rm.remove(regularMenu);
break;
}
Related
I'm doing a project were I need to remove letters systematically from an ArrayList as they show up in the words that the user puts in. Then all the remaining characters are displayed and then the elimination process continues until only vowels are left.
I cant seem to get it to eliminate the characters without the program crashing.
Here's the problematic code:
public static void Mapper(){
Scanner make = new Scanner(System.in);
char Aphabets[] ={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
ArrayList<Character> Alpabets = new ArrayList<>();
String word = make.nextLine();
for (int i = 0; i < Aphabets.length; i++) {
Alpabets. add(i,Aphabets[i]);
}
for (int i = 0; i < word.length(); i++) {
Alpabets.remove(word.charAt(i));
}
System.out.println(Alpabets);
}
Change
Alpabets.remove(word.charAt(i));
to
Alpabets.remove((Object) word.charAt(i));
The issue is that List.remove has two implementations (it's an overloaded method):
One implementation that takes an index as argument: List.remove(int index) ("remove the 5th element from the list")
One that removes an actual object from the list List.remove(Object o) ("remove the number 5 from the list).
By calling using Alpabets.remove(word.charAt(i)); you're accidentally invoking the one that takes an index, and if you give it a "large enough" character (characters can be seen as numerical values in Java), you'll hit an index out of bounds in the remove method.
By casting the argument to Object, you force the correct method to be called.
Might you can also use map key and value and remove based on user input.
The method has to receive a String in format "[1,2,3,4,5]" with just integers inside, but it can also have "[1,2,3,[]]" or "[1,2,3,[1,2,3]]". I already have the code to just add the numbers to the list, but I can't figure out how to handle when I have another List inside.
I've thought of having a class List and when I find another brackets inside to call the function again, but don't know how to substring correctly when I see another opening bracket [.
After I remove the brackets I split the string like this:
String[] arr = string.split(",");
And start to add those results to the List I have to return with a for loop, my problem is when I see an opening bracket again [ I would have to substring and call with the resulting String my method again but don't know how to determine the closing bracket. What I've tried is to get the index of a closing bracket with indexOf:
String aux = arr[i];
int closingBracket = aux.indexOf("]");
But if I have an input string like [1,2,3,4,[,6] which shouldn't be accepted it will accept it.
What you need to do is figure out, on paper, what is called a finite state machine (FSM). When you encounter a token (comma, bracket, digit) you enter a particular state. Once in a certain state, you can only accept certain other tokens which may put you in a different state or leave you in the current one. You could have many different states which can accept different tokens and perform different actions.
For example.
When you see a digit, the next token may be.
1. Another digit
2. A closing bracket.
3. A comma.
Each of those tokens may prompt a different state and/or action.
1. Another digit - keep on processing since numbers have many digits.
2. closing bracket - save the number in a list and get the next list (See below)
3. comma - save the number and look for next number
Assuming you want to save all of this in a list of lists it would be easiest to start off with a List<Object> since you can save integers and lists of lists in that type of list with indefinite depths.
I also suggest you look at the Stack class. You may want to be pushing the current list and popping a recent one as your parsing depth changes.
Finally, to ensure your brackets are properly matched to the following. Increment a counter when you see a '[' and decrement the counter when you see a ']'. If the counter ever goes negative, you have too many right brackets. If at the end it is positive, you don't have enough right brackets.
For more on this check out Finite State Machines at Wikipedia.
I decided to include a small example of what I was talking about. It may not cover all possible edge cases but the purpose is illustrative.
public static void main(String[] args) {
String strlist =
"[1,2,113], [4,5,[5,2,10],1], [],[1,2,3,4,5,[10,11,12,13,[14,15]]]";
int bracketCount = 0;
int num = 0;
// inital list
List<Object> list = new ArrayList<>();
// hold sublists for precessing
Stack<List<Object>> stack = new Stack<>();
char[] chars = strlist.toCharArray();
for (int i = 0; i < chars.length; i++) {
char c = chars[i];
switch (c) {
// state1 left bracket - push current list on stack for later
// retrieval
// allocate new list and add it to one just pushed (remember,
// I still have its reference).
// Assign nlist to list
// increment bracket count
case '[':
stack.push(list);
List<Object> nlist = new ArrayList<>();
list.add(nlist);
list = nlist;
bracketCount++;
break;
// state2 right bracket - Finished processing current sublist.
// if previous tokens were not brackets, then add the
// number to the list and pop off the previous one.
// decrement bracket count
case ']':
if (chars[i - 1] != '[' && chars[i - 1] != ']') {
list.add(num);
}
list = stack.pop();
bracketCount--;
break;
// state3 - whitespace - ignore
case ' ':
case '\t':
break;
// state4 comma - if previous token was not a right bracket,
// then add number. Reset num for next number.
case ',':
if (chars[i - 1] != ']') {
list.add(num);
}
num = 0;
break;
// state5 digit - assumed to be a digit. Each time a digit
// is encountered, update the number
default:
num = num * 10 + c - '0';
}
if (bracketCount < 0) {
System.out.println("too many ] brackets at location " + i);
}
}
if (bracketCount > 0) {
System.out.println("insufficent number of ] brackets");
}
System.out.println(list);
}
}
Note that in the above example, the "states" are rather "pseudo states." That is you don't need to check the current state you are in in order to determine how to process the current token or flag an error.
The program does one thing, depending on the users input, it removes an arraylist object and will ask you if u you want to remove another object, however, if the same object tries to be removed, i need the program to know and output 'such object does not exist', for example, 'remove "3"', then remove "3" again, the program output's "3" does not exist, the problem is that i have no idea how to implement it, what i have does not do much either. My theory is that you have to use boolean to check if the arraylist object is there in the first place, if it is: remove it, if not: output "not there".
here's what i have:
String[] id1 = { "1", "studentA" };
ArrayList<String> jim = new ArrayList<String>(Arrays.asList(id1));
System.out.println("would you like to remove an id? if so type in "
+ "the id number, otherwise type: no");
Scanner sc = new Scanner(System.in);
String i = sc.next();
int position = -1;
position = jim.indexOf(sc) - 1;
if (position == -1) {
System.out.println("not found in list");
} else {
System.out.println("found and removed");
jim.remove(i);
}
System.out
.println("would you like to remove another id? if so type in "
+ "the id number, otherwise type: no");
Scanner sc2 = new Scanner(System.in);
String j = sc.next();
int position2 = -1;
position2 = jim.indexOf(sc) - 1;
if (position2 == -1) {
System.out.println("not found in list");
} else {
System.out.println("found and removed");
jim.remove(j);
}
If you want your program to keep on asking for user input, you need a loop, for example a while-loop, which will only terminate if the user inputs no. In addition to that, you can simply use List.remove() for removing the element, and inspect the return value (true if the item was in the list and was removed) to give the correct feedback to the user:
String[] elements = { "1", "studentA" };
ArrayList<String> list = new ArrayList<String>(Arrays.asList(elements));
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("would you like to remove an id? if so type in "
+ "the id, otherwise type: no");
String input = sc.next();
if ("no".equalsIgnoreCase(input)) {
break; // exit the loop
}
if (list.remove(input)) {
System.out.println("found and removed");
} else {
System.out.println("not found in list");
}
}
I would suggest using public boolean remove(Object o) and this will return either true or false if the element is apart of the ArrayList or not respectively. You can set some boolean variable to equal that, and use an if statement to output your desired response.
boolean contains(Object o) would check if the ArrayList contains the object, you could scan through the list and check if it is there or not. You could also use the E get(int index) to scan through and check if the strings are equal to each other using a loop.
I want to find the index of the start up letter and then show the index of that item in array or array list in java.
Example: I have:
String[] arr={"apple","at","book","bad","car","cat"};
when I input a: then i will get index =0, b: i will get index=2, c: i will get index=4
Because my array item is over 20,000 , so using linear Search is too slow.
and my list is unsorted, so i can't use Binary Search also.
I want to get index of the item like the example above, what can i solve with this?
You can run some initialization code (before the user starts to type letters in).
// initialize an array that has a cell for each letter with value -1
int[] firstIndexes = new int[26];
for(int i=0;i<firstIndexes.length;i++) {
firstIndexes[i] = -1;
}
// loop over original array and look for each letter's first occurence
for(int i=0;i<wordsArray.length;i++) {
char c=wordsArray[i][0];
if(firstIndexes[c-'a'] < 0) {
firstIndexes[c-'a'] = i;
}
}
Then when the user types a letter you just need to find its index in the 'firstIndexes' array.
If you want to get all the indexes of words starting with a certain letter then try this one:
While adding the Words to your Array/list (that will hold all your words) you could also add it to a map that will hold all indexes for every first letters.
Map<String, ArrayList<Integer>> myMap = new HashMap<String, ArrayList<Integer>>();
public void yourmethod() {
//adding all your words to an Array/arraylist goes here. (arr[] in this case)
string firstLetter = yourword.substring(0,1);
if(myMap.constainsKey(firstLetter)) {
myMap.get(letter).add(yourword);
} else {
myMap.put(firstLetter, yourword);
}
}
I am creating a program that lets you store 10 items in an array. What I haven't been able to get the program to do is give an error if one of the entered items already exists in the array.
So, for example, if the array looks like [banana, potato, 3, 4, yes, ...] and I enter banana again, it should say "Item has already been stored" and ask me to re-enter the value. The code I currently have is:
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
int stringNumber = 0;
String[] stringArray = new String[10];
for (int i = 0; i <= stringArray.length; i++) {
out.println("\nEnter a string");
String input = keyboard.next();
stringArray[stringNumber] = input;
out.println("\"" + stringArray[stringNumber] + "\"" + " has been stored.");
PrintArray(stringArray);
stringNumber++;
You can use nested loops to go through the array to see if the new input exists. It would be better to do this in a function. Also when doing this you need to make sure that you are not at the first element or you will get a null pointer exception.
for (int i = 0; i <= stringArray.length; i++) {
boolean isInArray = false;
System.out.println("\nEnter a string");
String input = keyboard.next();
if (i > 0) {
for (int j = 0; j < stringArray.length; j++) {
if (stringArray[j].equalsIgnoreCase(input)) {
isInArray = true;
break;
}
}
}
if (!isInArray) {
stringArray[stringNumber] = input;
} else {
System.out.println("\"" + stringArray[stringNumber-1] + "\""
+ " has been stored.");
}
PrintArray(stringArray);
stringNumber++;
}
It's always better to use a HashSet when you don't want to store duplicates. Then use HashSet#contains() method to check if element is already there. If ordering is important, then use LinkedHashSet.
If you really want to use an array, you can write a utility method contains() for an array. Pass the array, and the value to search for.
public static boolean contains(String[] array, String value) {
// Iterate over the array using for loop
// For each string, check if it equals to value.
// Return true, if it is equal, else continue iteration
// After the iteration ends, directly return false.
}
For iterating over the array, check enhanced for statement.
For comparing String, use String#equals(Object) method.
When you got the String input, you can create a method that will :
Go through the entire array and check if the string is in it (you can use equals() to check content of Strings)
Returns a boolean value wheter the string is in the array or not
Then just add a while structure to re-ask for an input
Basically it can look like this :
String input = "";
do {
input = keyboard.next();
}while(!checkString(input))
The checkString method will just go through all the array(using a for loop as you did to add elements) and returns the appropriate boolean value.
Without introducing some order in your array and without using an addition structure for instance HashSet, you will have to look through the whole array and compare the new item to each of the items already present in the array.
For me the best solution is to have a helper HashSet to check the item for presence.
Also have a look at this question.
To avoid you should use an Set instead of an array and loop until size = 10.
If you need to keep an array, you can use the .contains() method to check if the item is already present in the array.
while (no input or duplicated){
ask for a new string
if (not duplicated) {
store the string in the array
break;
}
}
You should check the input value in array before inserting into it. You can write a method like exists which accepts String[] & String as input parameter, and find the string into the String array, if it finds the result then return true else false.
public boolean exists(String[] strs, String search){
for(String str : strs){
if(str.equals(search))
return true;
}
return false;
}
performance would be O(n) as it searchs linearly.