How to search for an Object in ArrayList? - java

I want search for an object in an arraylist using one of it attribute: String name.
I have printed out Item Found here, and this works just fine.
public static void searchItems() {
// variable declaration
String itemSearch;
// collect value of variable using Scanner class
System.out.println("\t\tSEARCH ITEMS");
System.out.println("Enter item name: ");
itemSearch = input.next();
//search for an item
for (int i=0; i<itemList.size();i++) {
if (itemList.get(i).name.equalsIgnoreCase(itemSearch)) {
System.out.println("\t\t[ITEM FOUND]");
}
}
}
However, I want to notify when the item is not found as well. When I add else to this for loop, the String itemSeacrh gets matched (might not be the exact right term, sorry) with all the objects in the arraylist, and prints out the notification for every object index.
Let me explain. Suppose, objects: book, pen and pencil are stored in the ArrayList itemList in that respective order and, the for loop is modified the following way:
for (int i=0; i<itemList.size();i++) {
if (itemList.get(i).name.equalsIgnoreCase(itemSearch)) {
System.out.println("\t\t[ITEM FOUND]");
}
else {
System.out.println("\t\t[ITEM NOT FOUND]");
}
}
I want to search for the book. When I enter book as the itemSearch the following get printed in the console:
SEARCH ITEMS
Enter item name:
book
[ITEM FOUND]
[ITEM NOT FOUND]
[ITEM NOT FOUND]
As you can see, it checks and prints that the book is not found in other objects, which in not what I exactly had in mind. I want it to print item found or either item not found, not both at the same time.
Thank you. I hope you understand my query.

created the list and the search item:
List<String> list = new ArrayList<String>();
list.add("book");
list.add("pencil");
list.add("note");
String itemToBeSearched = "book"; // taken as example
if(check(list,itemToBeSearched)){
System.out.println("ITEM FOUND");
}
else
{
System.out.println("NOT FOUND");
}
then the item check function is
public static boolean check(List<String> list, String itemToBeSearched){
boolean isItemFound =false;
for(String singleItem: list){
if(singleItem.equalsIgnoreCase(itemToBeSearched)){
isItemFound = true;
return isItemFound;
}
}
return isItemFound;
}
and it's working for me, please try this and let us know :)

The easiest way to do this is to print when you have found the book, and return. This way you will stop iterating once the book is found, and leave the function immediatly:
for (int i=0; i<itemList.size();i++) {
if (itemList.get(i).name.equalsIgnoreCase(itemSearch)) {
System.out.println("\t\t[ITEM FOUND]");
return;
}
}
System.out.println("\t\t[ITEM NOT FOUND]");
This will not allow you to do any further processing of the book after finding, so you may want to store the book in a variable outside the loop, and execute some code in a conditional:
Item item = null;
for (int i=0; i<itemList.size();i++) {
if (itemList.get(i).name.equalsIgnoreCase(itemSearch)) {
item = itemList.get();
break;
}
}
if null != item {
System.out.println("\t\t[ITEM FOUND]");
// do some stuff ...
} else {
System.out.println("\t\t[ITEM NOT FOUND]");
// do some other stuff ...
}
As a final note, look into using for-each loops as they are generally easier to read and faster than typical for loops:
for (Item item: itemList) {
// do some stuff ...
}

All other methods mentioned by other users seems good. Just to expose you to something new, here's my 2 cents. You could use Java Stream API to find any that matches your search term. I find it more readable but it is my personal preference.
class Item {
String name;
public Item(String name) {
this.name = name;
}
}
public class Test {
public static void main(String[] args) {
// Mock your senario which you have a search term and
// array of object with a public property 'name'
String itemSearch = "test1";
List<Item> itemList = List.of(new Item("test4"), new Item("test2"), new Item("test3"), new Item("test1"));
boolean searchTermExists = itemList
// Create a stream of items from the item list
.stream()
// Searching if any matches the condition (Predicate) and
// return as soon as we find a match
.anyMatch((item) -> item.name.equalsIgnoreCase(itemSearch));
if(searchTermExists) {
System.out.println("\t\t[ITEM FOUND]");
}else {
System.out.println("\t\t[ITEM NOT FOUND]");
}
}
}
And if you want to get the actual first item, then you could use
Item foundItem = itemList
.stream()
.filter((item) -> item.name.equalsIgnoreCase(itemSearch))
.findFirst()
.orElse(null);
System.out.println(foundItem);

there are many ways to search for an item
so after adding the items to the list
use a string to compare with the original item
so if the item is not found a statement will be printed after the loop ends
System.out.println("Enter an item to search for:");
String item = sc.nextLine();
String notFound = null;
here is the code i used to search for a "String" in a list using the "matches" method
System.out.println("Enter an item to search for:");
String item = sc.nextLine();
String notFound = null;
for (int i = 0; i < list.size(); i++) {
boolean check = list.get(i).matches(item);
if(check){
System.out.println("item is found.");
notFound=item;
break;
}
}
if(notFound == null){
System.out.println("item not found.");
}

Related

stuck with a malfunctioning while loop

I'm stuck with this problem in home work for a long time now, would appreciate your professional help.
I need to simulate filling up rockets destined for a "mission to Mars" with all kinds of items arranged already in an array list. Maximum weight of each rocket including cargo is a given (18,000 Kg), as well as rocket net weight (10,000 Kg) and each item's weight (Item object includes fields "weight" and "itemType", such as "building material", "water", etc,.)
Instructions are to fill each rocket until it's fully loaded and only then create another one. It seems that my fellow students ignored this instruction so their code cannot help.
Sorting the array in ascending / descending order according to weight does not solve the problem.
My problem is that although I have used while loops all over, rockets refuse to fill up despite still having space left that can be filled with an item still left on the list. Loop won't skip the next 2-3 items (the most I managed to get is skipping one item) and find the one item that can still be loaded.
Bellow is also the list of items.
public ArrayList<U1> loadU1(ArrayList<Item> items) {
ArrayList<U1> fleetU1 = new ArrayList();
int i = 0;
Iterator<Item> iterator = items.iterator();
while (iterator.hasNext()) {
U1 rocketU1 = new U1(); // create new rocket with zero cargo
while (rocketU1.canCarry(items.get(i))) { // "canCarry" checks if item's weight fits in:
/* public final boolean canCarry(Item cargo){
if(currentRocketWeight + cargo.weight <= maxRocketWeight){
return true;
} else {
return false; }} */
rocketU1.carry(items.get(i));
// "carry" updates rocket total weight - no more than 18000 Kg including rocket net weight 10000 Kg, i.e. max cargo weight is 8000 Kg:
/* public final int carry(Item cargo){
currentRocketWeight += cargo.weight;
return currentRocketWeight;}
*/
items.remove(i); // remove loaded item from list
}
fleetU1.add(rocketU1); // add rocket to fleet
}
return fleetU1;
}
/*arraylist "items" - "phase-1.txt":
building tools=2000
building tools=2000
building tools=2000
building tools=5000
building tools=5000
building tools=2000
building tools=1000
building tools=5000
building tools=6000
shelter equipment=5000
construction equipment=5000
plants=1000
steel=8000
books=1000
water=5000*/
public ArrayList<Item> loadItems(int phaseNum) {
try {
switch (phaseNum) {
case 1:
out.println("Loading phase 1:");
fileName = "phase-1.txt";
break;
case 2:
out.println("Loading phase 2:");
fileName = "phase-2.txt";
break;
default:
out.println("argument must be 1 or 2");
}
File file = new File(fileName);
Scanner scanner = new Scanner(file);
while (scanner.hasNextLine()) {
lineFromFile = scanner.nextLine();
String[] list = lineFromFile.split("=");
Item item = new Item(); //(list[0], );
item.itemType = list[0];
item.weight = Integer.parseInt(list[1]);
itemList.add(item); // create ArrayList of items
}
scanner.close();
} catch (Exception ex) {
ex.printStackTrace();
}
return itemList;
}
You need to iterate the items per rocket.
// create a copy of the items so we can remove without harm to the caller
List<Items> ourList = new ArrayList<>(items);
// you should probably sort the list by weight, descending order
while (!ourList.isEmpty()) {
// we need a rocket.
U1 rocket = new U1();
// go through all the items and load if item fits
Iterator<Item> iterator = ourList.iterator();
while (iterator.hasNext()) {
// the next() call that's mentioned in the comment
Item item = iterator.next();
if (rocket.canCarry(item)) {
rocket.carry(item);
// you need to remove from the iterator itself, not from the list
// or you will get an exception because that makes the iterator invalid
// it will remove from the underlying list as well though
iterator.remove();
}
}
fleet.add(rocket);
}
You need to have one method to fill a rocket and then call that method in a loop while there is still cargo left to load. To make this work without recursive calls I have changed the array of rockets, `fleet', to be a class member
private List<Item> loadRocket(List<Item> items) {
Iterator<Item> iterator = items.iterator();
List<Item> loaded = new ArrayList<>();
U1 rocketU1 = new U1();
while (iterator.hasNext()) {
Item item = iterator.next();
if (rocketU1.canCarry(item)) {
rocketU1.carry(item);
loaded.add(item);
}
}
items.removeAll(loaded);
fleetU1.add(rocketU1);
return items;
}
And then call it in a loop
while (!items.isEmpty()) {
items = loadRocket(items);
}
If you don't want to have the ´fleetas a class member you could move the creation of the rocket and adding to thefleetlist to outside of ´loadRocket and instead send it as a parameter.
while (!items.isEmpty()) {
U1 rocket = new U1();
items = loadRocket(rocket, items);
fleet.add(rocket);
}
So here what I would do:
For each item, I would try to place it in a rocket already in the fleet; if not possible, I would add a new rocket to the fleet. If the item cannot fit even in an empty rocket, it is kept in the input list, otherwise, it is removed:
public List<U1> loadU1(List<Item> items) {
List<U1> fleetU1 = new ArrayList<>();
Iterator<Item> iterator = items.iterator();
while (iterator.hasNext()) {
Item item = iterator.next();
U1 rocketU1 = null;
for (U1 u1: fleetU1) {
if (u1.canCarry(item)) {
rocketU1 = u1;
break;
}
}
if (rocketU1 == null) {
rocketU1 = new U1();
if (!rocketU1.canCarry(item)) {
// the item is too heavy
continue;
}
fleetU1.add(rocketU1);
}
rocketU1.carry(item);
iterator.remove();
}
return fleetU1;
}

how to compare every item from array to all items from another arraylist

First, I read data and rules, then I
iterate over data with rules, but I need help in this step please
I already make iteration for each rule over all rows
but it doesn't work properly
My comparison is not currently working.
Is there is comparison better than this?
Here is my code:
//for each rule
for( Rule rule : rules.getRules()) {
// System.out.println("Rules"+ rule);
// for read all transactions in database such each rule should iterate through okkk
for(List<Integer> transaction : database.getTransactions()) {
// System.out.println("transaction"+ transaction);
if(transaction.contains(rule.getItemset1().toString())) {
// for each item in transaction
Iterator<Integer> it = transaction.iterator();
while (it.hasNext()) {
// get the item
Integer item = (Integer) it.next();
if(rule.getItemset2().equals(it)) {
}
else {
String x=rule.getItemset2().toString();
item= Integer.parseInt(x);
// it=Arrays.toString(rule.getItemset2());
}
}
}
}
}

What is the best approach to split an Arraylist based on their values

I would like to split an ArrayList that I am looping trough and set a field called active which can be true or false. But at the end of loop I would like to split this collection in two groups.. active = false and active = true, so doing this I won't need to search in database twice..
for example:
private List<Classes> searchClasses(ClassItems listItems) {
List<ClassItem> items = new ArrayList<ClassItem>();
for (Iterator<ClassItem> iterator = listItems.getItems().iterator(); iterator.hasNext();) {
ClassItems item = iterator.next();
ClassEntityManager classEnt = ClassEntityManager.search(item.getId);
if(classEnt.active()){
item.setActive(true);
items.add(item);
}
}
return items;
}
What is the best approach to do this??
Make two lists instead of one.
if(classEnt.active()) {
activeItems.add(item);
item.setActive(true);
} else {
inactiveItems.add(item);
}
Use two collections, one for actives and the other for not actives.
When you fetch the data from the DB, simply put the CalssItem in the correct list:
private List<ClassItem> searchClasses(ClassItems listItems) {
List<ClassItem> activeItems= new ArrayList<ClassItem>();
List<ClassItem> notActiveItems= new ArrayList<ClassItem>();
Iterator<ClassItem> i = listItems.getItems().iterator();
while(i.hasNext()) { //This is a better approach.
ClassEntityManager classEnt = ClassEntityManager.search(i.next().getId);
if(classEnt.active()){
item.setActive(true);
activeItems.add(item);
}else{
item.setActive(false);
notActiveItems.add(item);
}
}
List<ClassItem> ret = new ArrayList<ClassItem>(activeItems);
ret.addAll(notActiveItems);
return ret;
}
BUT, in this way, both activeItems and notActiveItems are unreacheable. Best thing to do is to have a loop outside your method that checks if the ClassItem is active or not. In this way both activeItems and notActiveItems can be deleted from the method:
private List<ClassItem> searchClasses(ClassItems listItems) {
List<ClassItem> items= new ArrayList<ClassItem>();
Iterator<ClassItem> i = listItems.getItems().iterator();
while(i.hasNext()) { //This is a better approach.
ClassEntityManager classEnt = ClassEntityManager.search(i.next().getId);
item.setActive(classEnt.active());
items.add(item);
}
return items;
}
And to use the list:
List<ClassItem> items = searchClasses(classItems);
for(ClassItem item: items){
if(item.isActive()){
//do something
}else{
//do something else
}
}
Better yet is to use the magnificient and beautiful Java 8 Stream API:
List<ClassItem> active = items.stream().filter(x->x.isActive).collect(Collectors.toList());
List<ClassItem> notActive = items.stream().filter(x->!x.isActive).collect(Collectors.toList());
or the one liner:
List<ClassItem> active = searchClasses(classItems).stream().filter(x->x.isActive).collect(Collectors.toList());
NOTES:
Your code has a return type of List<Classes>, while the returned value is of List<ClassItem>. Which is right?
Your iterator has a generic type of ClassItem while the next() method returns a ClassItems object. Which is right?

How to return multiple values within a search function(array) in Java

I have a search function in a class that searches through an array by a String(Department of work) and a count.
In the main the program will ask the user what category does he/she wants to search for. Example: library ; the program should give all the books that are in that specific department (there is a function that lets the user add books)
The problem is that the program only returns one book and not the all the books that are associated within that Category.
Your function should not return an single index it should return a collection of indexes.
For example.
public static Collection<Integers> Searchdep(EmployeeClass EmployeeArr[], String department, int size) {
List<Integer> intList = new ArrayList<Integer>();
for(int i=0; i<size; i++)
{
if(EmployeeArr[i].Department.equals(department)) {
intList.add(i);
}
}
return intList;
}
Then in your main check for size of the collection, if it is zero that mean nothing was found.
Theses the line need to change
index=EmployeeClass.SearchDep(EmpList,department,count);
JOptionPane.showMessageDialog(null,index);
to
Collection<Integer> returnedCollection = EmployeeClass.SearchDep(EmpList,department,count);
if(returnedCollection.isEmpty()){
JOptionPane.showMessageDialog(null,"Nothing was found");
} else {
StringBuilder str = new StringBuilder();
for(Integer integer: returnedCollection){
str.appened(EmpList[integer].ReturnStringInfo());
str.appened(", ");
}
JOptionPane.showMessageDialog(null,"Indexed are : "+ str.toString());
}
Just return an array of indices instead of a single index. For example:
public static List<Integer> Searchdep(EmployeeClass EmployeeArr[], String department, int size){
List<Integer> result = new ArrayList<Integer>();
for(int i=0; i<size; i++){
if(EmployeeArr[i].Department.equals(department)){
result.add(i);
}
}
return result;
}
The best option here is to pass a Visitor action to apply to each employee found. In Java 8, this would be a lambda but in Java 6 or 7 this would be an anonymous inner class.
Then you might return the count found so you can detect when there was no matches.

Removing a String from an ArrayList

So I have a problem that takes the names of people from a user and stores them in an ArrayList(personalNames). After that I need to take that list and remove any name that has anything besides letters a-z (anything with numbers or symbols) in it and put them into a separate ArrayList(errorProneNames) that holds the errors. Could someone help me with the removal part?
public class NameList {
public static void main(String[] args) {
ArrayList<String> personalNames = new ArrayList<String>();
Scanner input = new Scanner(System.in);
String answer;
do{
System.out.println("Enter the personal Names: ");
String names = input.next();
personalNames.add(names);
System.out.println("would you like to enter another name (yes/no)?");
answer = input.next();
} while (answer.equalsIgnoreCase("yes"));
ArrayList<String> errorProneNames = new ArrayList<String>();
}
}
If it's the "how do I remove an element from an ArrayList<>" part which is causing problems, and you want to check all the values, you probably want to use an Iterator and call remove on that:
for (Iterator<String> iterator = personalNames.iterator(); iterator.hasNext(); ) {
String name = iterator.next();
if (isErrorProne(name)) {
iterator.remove();
}
}
Note that you mustn't remove an element from a collection while you're iterating over it in an enhanced-for loop except with the iterator. So this would be wrong:
// BAD CODE: DO NOT USE
for (String name : personalNames) {
if (isErrorProne(name)) {
personalNames.remove(name);
}
}
That will throw a ConcurrentModificationException.
Another option would be to create a new list of good names:
List<String> goodNames = new ArrayList<>();
for (String name : personalNames) {
if (!isErrorProne(name)) {
goodNames.add(name);
}
}
Now, if your real problem is that you don't know how to write the isErrorProne method, that's a different matter. I suspect that you want to use a regular expression to check that the name only contains letters, spaces, hyphens, and perhaps apostrophes - but you should think carefully about exactly what you want here. So you might want:
private static boolean isErrorProne(String name) {
return !name.matches("^[a-zA-Z \\-']+$");
}
Note that that won't cope with accented characters, for example. Maybe that's okay for your situation - maybe it's not. You need to consider exactly what you want to allow, and adjust the regular expression accordingly.
You may also want to consider expressing it in terms of whether something is a good name rather than whether it's a bad name - particularly if you use the last approach of building up a new list of good names.
Here is your solution :
String regex = "[a-zA-Z]*";
for (String temp : personalNames ) {
if (!temp.matches(regex)){
errorProneNames.add(temp);
personalNames.remove(temp);
}
}
You can use the remove() method of ArrayList
personalNames.remove("stringToBeRemoved");
Lot of overloaded methods are available. You can delete with index, Object(String itself) etc. You can see Javadocs for more info.
Also to remove all String having anything but a-z letters you can use regex. Logic is as follows
String regex = "[a-zA-Z]*";
String testString = "abc1";
if(!testString.matches(regex)){
System.out.println("Remove this");
}
As Jon pointed out while iterating over the List do not use the Lists's remove() method but the iterators remove() method.
There are two ways you can do this:
The first is to iterate backwards through the list, remove them, then add them into the second list. I say to do it backwards, because it will change the index.
for (int i = personalNames.size()-1; i >=0; i++) {
if (isBadName(personalNames.get(i)]){
errorProneNames.add(personalNames.get(i));
personalNames.remove(i);
}
}
The second way is to use the Iterator provided by ArrayList (personalNames.iterator()). This will allow you to go forward.
I would probably do this
// Check that the string contains only letters.
private static boolean onlyLetters(String in) {
if (in == null) {
return false;
}
for (char c : in.toCharArray()) {
if (!Character.isLetter(c)) {
return false;
}
}
return true;
}
public static void main(String[] args) {
ArrayList<String> personalNames = new ArrayList<String>();
ArrayList<String> errorProneNames = new ArrayList<String>(); // keep this list here.
Scanner input = new Scanner(System.in);
String answer;
do {
System.out.println("Enter the personal Names: ");
String names = input.next();
if (onlyLetters(names)) { // test on input.
personalNames.add(names); // good.
} else {
errorProneNames.add(names); // bad.
}
System.out
.println("would you like to enter another name (yes/no)?");
answer = input.next();
} while (answer.equalsIgnoreCase("yes"));
}
get an iterator from list, while itr has next element give it to a method for example isNotProneName which takes a String and returns true or false, if the given String matches not your needs. if false returned remove string from itr and add it to the other list
Use regex [a-zA-Z ]+ with String.matches to test error-prone name and Iterator to remove.
Iterator<String> it=personalNames.iterator();
while(it.hasNext()){
String name=it.next();
if(name.matches("[a-zA-Z ]+")){
it.remove();
}
}

Categories

Resources