Searching an ArrayList - java

I currently have 3 classes, a main class containing a GUI, in which i'm calling this method, a customer class containing the data, and a customerList class which gathers the data from the customer class, puts it into an array list, and also contains the search arraylist method.
I'm trying to implement a search method which can be called from my main class on an action event handler. I'm having a few problems though.
Whenever I run the method, the " System.out.println(customer.returnFamilyName());" line always displays the first familyname in my arraylist.
Don't hesitate to ask for more information, I'm not sure how well i've explained this.
Here is my method:
public void searchCustomer(String familyName) {
int index = 0;
boolean found = false;
customer customer;
while(index < CustomerList.size() && !found) {
customer = CustomerList.get(index);
if(customer.returnFamilyName().equalsIgnoreCase(familyName)) {
found = true;
break;
}
if(found == true) {
;
}
System.out.println(customer.returnFamilyName());
index++;
return;
}
}

It's not clear from your question what the intended behaivor actually is. Besides that, what is this ?
if (found == true);
Presumably you meant :
if (found) {
System.out.println...
}
But what if the same last name occurs twice in your list? Also why aren't using a Map instead of a List? Lookup will go from being O(n) to O(1)

Drop the ; in if (found == true); because that reads as: if this condition is true, do notihng and use braces always:
if (found == true) {
System.out.println(customer.returnFamilyName());
}
Also, include the increment inside the while loop, otherwise you are not really iterating anything.
This code seems to work because your first element happens to coincide with the searched element, try with a different one and you'll end up in a infinite loop.
Try with a version like this:
public void searchCustomer( String familyName ) {
for ( customer current : CustomerList ) {
if ( current.returnFamilyName().equalsIgnoreCase( familyName )) {
System.out.println( current.returnFamilyName() );
break;
}
}
}
Some additional remarks:
In Java clases should start with uppercase, so the class name should be declared as Customer instead of customer and variables start with lowercase, hence CustomerList should be customerList. Methods may avoid the return part and be named with a get
Also, search methods should better return the found value instead of printing it, so your final version could look like this:
public Customer searchCustomer( String familyName ) {
for ( Customer current : customerList ) {
if ( current.getFamilyName().equalsIgnoreCase( familyName ) ) {
return current;
}
}
return null;
}

You never increment index.
The code should be:
public void searchCustomer(String familyName) {
for (customer customer : CustomerList) {
if (customer.returnFamilyName().equalsIgnoreCase(familyName)) {
System.out.println(customer.returnFamilyName());
break;
}
}
}
Also, the 'customer' class should be called 'Customer' as class names should start with a capital, 'returnFamilyName' should be 'getFamilyName' as accessor methods by convention are named 'get' + the field name and 'CustomerList' should be 'customerList' as field names are supposed to start with a lowercase letter.

I would suggest try this:
System.out.println(customer.returnFamilyName());
index++;
if(found == true) { return;}

Don't forget to increment the while loop or it has the potential to run indefinitely.
You can elect to use what is known as an "enhanced for-loop", which allows you to eschew the need to increment values over CustomerList entirely. You have an object customer, so we can use that as follows:
for (customer cus: CustomerList) {
if(cus.returnFamilyName().equalsIgnoreCase(familyName)) {
System.out.println(cus.returnFamilyName());
return;
}
}
If you elect to stick with your original code (which is fine), then observe the changes in your code below.
while(index < CustomerList.size()) {
customer = CustomerList.get(index);
if (customer.returnFamilyName().equalsIgnoreCase(familyName)) {
System.out.println(customer.returnFamilyName());
break;
} else {
index++;
}
}

Related

Is there a way in Java to see if one field exists, then all fields must be populated?

I have addresses that need to be validated. Currently, we take in Street Address, City, Zip. I want to make it so that if one of these is populated, then the other two must be populated as well (the other 2 cannot be blank).
It would look like this
if(!StringUtils.hasText(AddressLine)) {
???
Use String method .equals()
if (!AdressLine.equals(""){
if(!city.equals("") & !Zip.equals("")){
//Do something
}
}
If you can have a Null String, just add: if word != equals, then...
Simple approach:
boolean allBlankOrNot(String... parts) {
Boolean temp = null;
for(String part : parts) {
//on the first element set the expectation: either blank or not
if( temp == null ) {
temp = StringUtils.isBlank(part);
//any other element needs to be the same, i.e. if you get a different state you'Re done and return false
} else if( temp != StringUtils.isBlank(part)) {
return false;
}
}
//no early out, so all are the same
return true;
}
Better yet, use a Predicate:
boolean allMatchOrDont(Predicate<String> predicate, String... parts) {
//same as above but instead of StringUtils.isBlank(...) use predicate.test(...)
}
Then call it like this:
boolean valid = allMatchOrDont(s -> StringUtils.isBlank(s), streetAddress, city, zip);

Using java "for each" and "continue" in a loop

I have a big method which looks like this :
for (Person person : persons) {
if (!person.isValid()) {
continue;
}
....
boolean isDeleted = deletePersonFromDB1(person);
if (!isDeleted) {
continue;
}
....
}
Basically I want to delete a list of persons from differents DB sources. If any operation fails, I want to continue to next person.
I would like to simplify like this and put my business logic inside a method :
for (Person person : persons) {
checkValidityAndDelete(person)
}
But unfortunately, I cannot use the word continue inside my method checkValidityAndDelete
Make your checkValidityAndDelete method return a boolean to indicate whether the person is both valid and was deleted:
private boolean checkValidityAndDelete(Person person) {
return person.isValid() && deletePersonFromDB1(person);
}
So, if checkValidityAndDelete returns false, you can then continue, if it returns true, you can proceed with the rest of your code logic. You can also achieve this without the use of continue if you wish to do so:
for (Person person : persons) {
if(checkValidityAndDelete(person)) { // If the person is valid,
// perform logic...
}
// if not valid, skip if, and continue to next person...
}
Another option if you're looking to pull everything in the loop out to another method is simply return~ing from it to trigger the method to stop.
public void checkValidity(final Person person) {
if (person.something) {
return;
// From the calling loop, this will act as a continue
// since the method call would stop, and so the next
// loop iteration would start.
}
// Do some more stuff
}

Reflecting changes to a variable in the caller in Java

I have a function that is supposed to return a place object, but I also need to test on whether something evaluates to false, and in addition the caller needs to know both of those pieces of information. I have the return type as Place but in Java there are no reference parameters, so if the following if-condition is true, I would like for some way to reflect that in the caller so I can check it, but I can't have more than one return type so I'm stuck as to what to do. My best shot was returning null but I just get the feeling that this is bad programming.
if ( directions.get(i).isLocked() )
Below is the complete function:
Place followDirection(String dir, boolean isLocked) {
dir = dir.toLowerCase(); // make sure the string is lowercase for comparisons
int i = 0;
for ( i = 0; i < directions.size(); i++ ) { // loop until we find a match, remember that if it's locked then we cnanot go in there
if ( directions.get(i).getDirection().equals(dir) ) {
if ( directions.get(i).isLocked() ) {
System.out.println("This room is locked, sorry");
}
else {
return directions.get(i).getToPlace(); // this means we found a match, return the destination
}
}
}
Place p = null;
return p;
}
Technically, there are two options if you don't want to return null (which does not seem bad by the way):
return an object that contains both return values
Pass in a mutable object as parameter.
The second option also feels somewhat dirty.
java is a call by value language but it is a little bit complicated. this language pass the pointers as a value and if you dont change the pointer you can change the object that pass to your function. for example if you pass an complex object to a function and in that function you change the value of a parameter of that object, the caller can see it, in your code you can pass an object than contains dir and isLocked , so you can change those parameters.
Place followDirection(MyObject obj) {
obj.dir = obj.dir.toLowerCase(); // make sure the string is lowercase for comparisons
int i = 0;
for ( i = 0; i < directions.size(); i++ ) { // loop until we find a match, remember that if it's locked then we cnanot go in there
if ( directions.get(i).getDirection().equals(obj.dir) ) {
if ( directions.get(i).isLocked() ) {
System.out.println("This room is locked, sorry");
}
else {
return directions.get(i).getToPlace(); // this means we found a match, return the destination
}
}
}
Place p = null;
return p;
}
MyObject contains :
String dir, boolean isLocked

Better way of returning from condition

Which way of returning from condition is better , Like the process1 and process 2 both does the same. But I want to know better way returning.
In both cases I don't want to enter inside of loop, I just want to return. I would like to know that, Is there any performance difference If I put return before control passes to end. I don't want Java Virtual Machine to check end of loop and returning from there. I thought If I put return Immediately when the condition not satisfied, then I could see minor performance difference and also code readability. Please suggest me the best way.
Let us consider the below scenarios.
Process1:
public Method()
{ //Method
Company company = new Company(); //Object
if (null != Address && null = Address.location()) //Condition
{
return company; //I want to return
}
for (Location location: Address.location())
{
//forloop
}
return company; //return
}
Process2:
public Method()
{
Company company = new Company();
if (null != Address && null != Address.location())
{
//enters loop
}
return company; // return
}
There will be some performance impact. Iterating complete objects from the for loop to verify the condition.
For example:
We can write like this.
if(condition is false){
return ;
else{
for(DataType ref: collection){
if(true){
return;// return from here, so that it will not iterate remaining elements.
}
}
}
ex 2:
if there is a logic after the if and that should not be executed, if the object is null.
if(object is null){
return ;
}
//Remaining logic here will not be executed, if the object is null. it's a good way of writing.
ex 3:
if there is no logic after the if and else, then directly return from the end of method.
if(object is null){
return
}else{
//process logic and return.
}
you can write something like this.
if(object is not null){
// return either from here.
}
return here is also fine...

Using a for each loop to find two elements in an array list

I need help writing a for each loop which searches through an array list called peoplelist of type people. The loop needs to search for the values String postcode and String name in the array. It then needs to return their ID if it is found, and null if it is not. Any sort of help would be great!
If the class People is written like a Java bean (i.e. with standard getter methods), something like this would do the job:
for (People person : peopleList) {
if (person.getName().equals(name) && person.getPostcode().equals(postCode))
return person.getId();
}
return null;
If a person's name or postcode can be null, you may want to flip the equals calls to avoid null pointer exceptions (e.g. name.equals(person.getName()) instead of person.getName().equals(name)).
Btw Person would be a better name.
Need to make a lot of assumptions about your classes, but something like this should suffice:
for (People person : peoplelist) {
if (person.getPostCode().equals(postcode) && person.getName().equals(name)) {
return person.getId();
}
}
// deal with not being found here - throw exception perhaps?
With “two elements”, do you mean “two attributes of some class”? If so, something along these lines would do:
String id = null;
for(People p : peoplelist) {
if(somePostcode.equals(p.postcode) && someName.equals(p.name)) {
id = p.id;
break; // no need to continue iterating, since result has been found
}
}
// result “id” is still null if the person was not found
//In case multiple persons match :)
List<String> result = new LinkedList<String>();
for (People person : peopleList) {
if (person.getName().equals(name) && person.getPostcode().equals(postCode))
result.add(person.getId());
}
if(result.isEmpty()){
return null;
}else{
return result;
}
People foundPerson;
for (People eachPeople : peoplelist )
{
if (Integer.valueOf(eachPeople.getID()) == 10054
&& "Jimmy".equals(eachPeople.getName()))
{
foundPerson= eachPeople;
break;
}
}
Assuming you have a Person bean, then if you want to retrieve all instances of Person whose postcode and name match some values, you may do something like this:
public List<Person> searchFirst(List<Person> persons, String postcode, String name) {
List<Person> matchingPersons = new ArrayList<Person>();
for (Person person : persons) {
if (person.getPostcode().equals(postcode) && person.getName().equals(name))
matchingPersons.add(person);
}
return matchingPersons;
}
Next time, you may want to show us your code, so we can help you in understanding what you're doing wrong :)

Categories