Searching object arraylist confusion - java

I wrote a method for searching an object in my arralist, however I need this search to take two parameters and compare them to the description of the object. What it is confusing me is that I do not know how to make my method take two parameter and those two parameters compare to one single description.
e.g Description of object: Blue Mustang
Now the search method has to take two parameters in this case one String "Blue" and one String "Mustang" and I do not have a clue how to do it. I found a way to just write the complete description as one parameter and works perfectly. I am leaving the method that I tried to change to look for two parameters and as well the method that takes one parameter and works fine. It is important to mention that the method also needs to look for cars that are not on loan so thats why there is also a comparison to the hire date since if the car is on loan will have one and if not it wouldn't.
Trying to change it to look for two parameters:
public Car searchCar(String description, String description2)
{
for (Car car : cars) {
if (car.getDescription().equals(description) && car.getDescription().equals(description2) && car.getHireDate().equals("")) {
System.out.println( ": " + car.getDescription() + " rate: £" + car.getDailyRate() + " Down payment: £"+ car.getDownPayment());
return car;
}
else if (car.getHireDate() != ("")) {
System.out.println("This car is rented!!");
}
else {
}
}
return null;
}
This is the one that takes one parameter and works fine:
public Car searchCar(String description)
{
for (Car car : cars) {
if (car.getDescription().equals(description) && car.getHireDate().equals("")) {
System.out.println( ": " + car.getDescription() + " rate: £" + car.getDailyRate() + " Down payment: £"+ car.getDownPayment());
return car;
}
else if (car.getHireDate() != ("")) {
System.out.println("This car is rented!!");
}
else {
}
}
return null;
}

description needs to be identical to description2
you could do :
String fulldescription=description+" "+description2;
and then
if (car.getDescription().equals(fulldescription)...
a different approach can be
if (car.getDescription().indexOf(description)>0 && car.getDescription().indexOf(description2)>0 )...

It's unlikely the description would be exactly equal to both parameters. Perhaps you're trying to match only part of the description?
Something like contains might be of interest.
Also note that this line:
else if (car.getHireDate() != ("")) {
will not work as you expect; you correctly compare strings in the previous statement (using equals) but fail to do so here.

First, you should define whether exact matches are necessary or if the parameters should be contained and there might be additional text in the description.
Exact matches
For exact matches, you can use the or-condition:
if ( (car.getDescription().equals(description) | car.getDescription().equals(description2) ) && car.getHireDate().equals("") ) {
...
}
This means that if the description exactly matches description or description2 you get a hit.
Alternatively you could concatenate the parameters if you know the order:
if ( car.getDescription().equals(description + " " + description2) && car.getHireDate().equals("") ) {
...
}
This would match "Blue Mustang" but not "Mustang Blue".
Optionally you could make the concatenated string a regular expression in order to allow for arbitrary whitespace:
if ( car.getDescription().matches("\\s*\\b" + description + "\\b\\s*\\b" + description2 + "\\b\\s*") && car.getHireDate().equals("") ) {
...
}
This would match " Blue Mustang " etc. but not "BlueMustang" due to the word boundary requirements ("\\b").
Note that there are many more possibilities so you should define how you want to match first.
Parameters contained
If you want to get all descriptions that contain both parameters, use contains(...) instead:
if ( car.getDescription().contains(description) && car.getDescription().contains(description2) && car.getHireDate().equals("") ) {
...
}
Note that this would match "Blue Ford Mustang", too ("Blue" and "Mustang" being the parameters).

In order to test for the occurence of substrings, you can use indexOf() (docs):
if (-1 != car.getDescription().indexOf(description) &&
-1 != && car.getDescription().indexOf(description2) &&
car.getHireDate().equals("")) {
you might want to make the comparison case-insensitive too.

I would suggest use contains and toLowerCase for String search. Also consider a variable argument search method like this:
public Car searchCar(String...descriptions) {
for (Car car : cars) {
if (car.getHireDate().equals("")) {
for (String d : descriptions) {
// assuming car.getDescription() != null
if (car.getDescription().toLowerCase().contains(d.toLowerCase())) {
System.out.println( ": " + car.getDescription() + " rate: £" + car.getDailyRate() + " Down payment: £"+ car.getDownPayment());
return car;
}
}
}
else
System.out.println("This car is rented!!");
}
return null;
}
Then you can call this method like:
Car c1 = searchCar("blue");
OR
Car c1 = searchCar("blue", "toyota");
OR
Car c1 = searchCar("blue", "red", "toyota", "mustang", "honda");

Consider encapsulating your search/match in a class which you can augment to include whatever search criteria you require.
Here is an example which satisfies your current requirements.
class CarSearch {
private boolean isIncludeHired;
private String[] descriptionWords;
private boolean isCaseInsensitive;
public void setIncludeHired(boolean b) {
isIncludeHired = b;
}
public void setCaseInsensitive(boolean b) {
this.isCaseInsensitive = b;
}
public void setDescriptionWords(String[] words) {
this.descriptionWords = words;
}
public boolean matches(Car car) {
boolean matches = true;
if (!isIncludeHired) {
if (car.getHireDate() != null) {
matches = false;
}
}
if (matches && descriptionWords != null) {
String description = car.getDescription();
if (isCaseInsensitive) {
description = description.toLowerCase();
}
boolean allMatch = true;
for (String word: descriptionWords) {
if (isCaseInsensitive) {
word = word.toLowerCase();
}
if (!description.contains(word)) {
allMatch = false;
break;
}
}
matches = allMatch;
}
return matches;
}
public List<Car> search(List<Car> cars) {
List<Car> matched = new ArrayList<Car>();
for (Car car: cars) {
if (matches(car)) {
matched.add(car);
}
}
return matched;
}
}
So now you could do something this:
CarSearch search = new CarSearch();
search.setCaseInsensitive(true);
search.setIncludeHired(false);
search.setDescriptionWords(new String[]{"blue", "mustang"});
List<Car> matches = search.search(cars);
You could also easily change your CarSearch class to allow other things, e.g. exact match, search by hire date, search by registration, etc.

Related

Identify a unique String

I have some strings read in from a file that look like this
"Anderson, T",CWS,SS,...
"Anderson, B",MIA,3B,...
"Galvis, F",CIN,SS,...
I need the user to input a name (such as "Anderson" or "Galvis") and if the name is insufficient to identify a unique player I need to print an error message.
So if the user wants to pick "Anderson, T" they would have to specify "Anderson, T").
Currently I have a function that takes in the name ("Anderson, T" or "Anderson, B") and it finds the correct string, the function can be found below
public static boolean findPlayer(String playerName) {
// Find specified player
int found = -1;
for (int j = 0; j < players.size(); j++) {
if (players.get(j).toString().toLowerCase().contains(playerName.toLowerCase())) {
found = 0;
break;
}
}
if (found == 0)
return true;
else
return false;
}
Is there a way for me to modify the code so that it takes in "Anderson" and then print out an error?
Since the method is named findPlayer, it should return the found player.
Since you want it to fail if there are multiple player matching the name, you could use an exception to indicate that.
You obviously want to know if no player is found, so you can return null, or change return type to Optional, or throw another exception to indicate that.
Here we'll go with exception for non-unique name, and null for not found:
public static Player findPlayer(String playerName) {
Pattern nameRegex = Pattern.compile(Pattern.quote(playerName), Pattern.CASE_INSENSITIVE);
Player foundPlayer = null;
for (Player player : players) {
if (nameRegex.matcher(player.toString()).find()) {
if (foundPlayer != null)
throw new IllegalArgumentException("Multiple player matches name: " + playerName);
foundPlayer = player;
}
}
return foundPlayer; // returns null if not found
}
Changed code to use regex for case-insensitive contains logic, so it doesn't create a lot of intermediate lower-case strings during the search.

Comparing two objects through a boolean method, within my car class

I am having trouble writing my main method within my car class. My class code is written as following;
public boolean compare (Car otherCar) {
return (model.equals(otherCar.model) && year == otherCar.year);
}
My problem is i am having trouble writing my main method i need to compare my "ferrari" car object with my "cobra" car object. I need to use an if/else statement and the method compare to compare the ferrari obj with the
cobra obj. And need to output "Same" if they are the same, or "Different" if they are different. All my other methods have been working fine besides this one.
Edit:
private String model;
private int year;
// default constructor
public Car()
{
model = "NA";
year = 0;
}
// overloaded constructor
public Car (String newModel, int newYear)
{
model = newModel;
year = newYear;
}
// mutator methods
public void setModel (String newModel)
{
model = newModel;
}
public void setYear (int newYear)
{
year = newYear;
}
// accessor methods
public String getModel()
{
return model;
}
public int getYear()
{
return year;
}
public boolean compare (Car otherCar)
{
return (model.equals(otherCar.model) && year == otherCar.year);
}
public void print()
{
System.out.println(model + " (" + year + ")");
}
}
My question is how should i write the if - else statement in my main method to compare these two objects using the compare method
Edit 2:` {
// Create an object of the class Car named ferrari
Car ferrari = new Car();
// Use the print method to print all information about the ferrari object.
ferrari.setModel("Ferrari");
ferrari.setYear(2010);
ferrari.print();
// Create an object of the class Car named cobra, passing parameters "Cobra" and 1967.
Car cobra = new Car("Cobra", 1967);
// Print information about the Cobra object using get methods.
System.out.println(cobra.getModel() + " " + cobra.getYear());
// Change the model of the cobra object to "Shelby Cobra".
cobra.setModel("Shelby Cobra");
// Change the year of the cobra object to 1963.
cobra.setYear(1963);
System.out.println(cobra.getModel() + " " + cobra.getYear());
// Use an if/else statement and the compare method to compare the ferrari obj with the
`
In your main method, you can simply write an if else for comparing cars and printing out like this,
if (ferrari.compare(cobra)) {
System.out.println("Both cars are same.");
} else {
System.out.println("Both cars are different.");
}
Another note, for printing objects values, you should better override toString() method that way you don't need to implement your print() method like you did. You can implement toString method like this,
public String toString() {
return String.format("model: %s, year: %s", model, year);
}
And then your if else can be written like this and will look better,
if (ferrari.compare(cobra)) {
System.out.println("("+ferrari + ") AND (" + cobra + ") cars are same");
} else {
System.out.println("("+ferrari + ") AND (" + cobra + ") cars are different");
}
Which will give following output,
(model: Ferrari, year: 2010) AND (model: Shelby Cobra, year: 1963) cars are different

how can I search the saved number

I want to create a program to save country code and search the country code. Also, there are at most 20 counters for saving country code. I am a new java beginner. I want to know what is the correct way to write the searchCoutryCode
method by using arrays to search the saved country code before?
public static void createCountryCode(String countryName, String countrycode) {
if (nameCounter >= 20) {
System.out.println("Full");
} else {
System.out.println("Saving the number of " + countryName + ":" + countryCode);
}
countryNameRec[countryNameCounter++] = countryName;
countryCounterRec[countryCounter++]= countryCode;
}
public static void searchCoutryCode(String countryName) {
for(int i = 0; i <=20; i++){
if(countryNameRec[i].equals(countryName)){
System.out.println("countryNameRec[i]+ " : "+ coutryCodeRec[i]");
} else {
System.out.println("No records");
}
}
}
This code assumes country names are unique. In your code you were giving a message about, list size full but adding records anyway. For this kind of problems as recomended by others using maps more suitable.
public static HashMap<String,String> countries = new HashMap<>();
public static void createCountryCode(String countryName, String countrycode) {
if (countries.size() >= 20) {
System.out.println("Full");
} else {
System.out.println("Saving the number of " + countryName + ":" + countrycode);
countries.put(countryName,countrycode);
}
}
public static void searchCoutryCode(String countryName) {
String countryCode = countries.get(countryName);
if(countryCode == null){
System.out.println("No records");
}
else{
System.out.println("countryName+ " : "+ countryCode");
}
}
Iterating in an array to find an element is not an efficient way.
Well, as you have only 20 elements, it will very probably not cause a real issue but whatever you could have more elements to handle later and this way of doing is besides verbose.
Using a binarySearch (Arrays.binarySearch()) with a sorted array or using a Map would be probably better.
Note that actually your searchCoutryCode() doesn't return nothing.
A search method have to return something : the element that it founds or nothing.
You could return String :
public static String searchCoutryCode(String countryName) {
...
}
or better Optional<String> to handle in a cleaner way the not found case :
public static Optional<String> searchCoutryCode(String countryName) {
...
}
I would recommend learning about Maps. They're a smarter version of arrays, and act like dictionaries with "keys" being like the words and "values" being like a definition. Your entire method can be replaced using a call to the containsValue() or containsKey() method from the java library.
However, if you want to use arrays, i would recommend looking into the binary search methods which are part of the Java Arrays library.

How can I compare all the values of an enum with a given array in java?

I have an enum class with values:
enum carBrand{BMW,HONDA,MERC,AUDI};
And there's an array called Sales with Array values:
sales[] = {CHEVVY, BMW , MERC, AUDI};
So how could I check that the sales[] has all the values of enum carBrand?
I'm trying to put it in a for loop as:
for(int i = 0; i<sales.length;i++){
if(carBrand.sales == sales[i]){
return true;
}
return false;
}
Add carBrand values to list
loop sales, remove the carBrand from the list
check if list is empty, if so they have all the values
Note: Class names should be names in PascalCase (CarBrand, Sales)
I would, personally, suggest using a list object rather than an Array where you are using such, however, this should work.
public static boolean checkArray(carBrand[] array) {
for (carBrand c : carBrand.values()) {
boolean found = false;
for (carBrand a : array) {
if (a == c) {
found = true;
break;
}
}
if (!found) {
return false;
}
}
return true;
}
where the "array" parameter would be invoked as the sales object in your code.
This code will return false if not every enum value exists within your array.
Off-topic:
Things like this are actually all over the internet - here, google, even Bing (as garbo as Bing is), so searching before requesting help, probably a viable choice
public class Enumeration {
enum carBrand{BMW,HONDA,MERC,AUDI};
public static void main(String[] args) {
String sales[] = {"CHEVVY", "BMW" , "MERC", "AUDI"};
for(carBrand brand:carBrand.values()) {
boolean bran=false;
for(int i=0;i<sales.length;i++) {
if(brand.toString()==sales[i]) {
bran=true;
break;
}
}
if(!bran==true) {
System.out.println("Sales doesn't have " +brand);
}
}
}
}

Using regular expressions in Java to do a partial search

ETA at 9:42 p.m. March 21: Dumb mistake. I made sure the original creation of the object made the name .toUpperCase(). The partial search didn't find the search term because they weren't capitalized. Edited code below. Thank you all for the help.
I'm trying to figure out how to use regular expressions to find out if any pattern of characters matches what's in the object.
For instance, if the name associated with the object was "StackOverflow," I'd like for someone to search "ck" and make the if statement true. So, why is my if statement here not returning true?
ETA: i.getName() returns a string. The program is looping through an ArrayList of objects to find which object has a name that matches the input.
System.out.println("What name or partial name would you like to filter?");
String name = input.nextLine();
int count = 0;
for (MyObject i: testObject) {
if (i.getName().matches(".*" + name.toUpperCase() + ".*")) {
count++;
}
}
You need to use toString(). You can not apply matches over an object.
Try that:
System.out.println("What name or partial name would you like to filter?");
String name = input.nextLine();
int count = 0;
for (Object i: testObject) {
if (i.getName().toString().matches(".*" + name + ".*")) {
count++;
}
}
I'm not sure why your code doesn't work, but see this working example, perhaps you have a small mistake somewhere.
Here's a MyObject class that has a name field:
class MyObject {
private final String name;
public MyObject(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
and here's the program that find matches:
List<MyObject> myObjects = new ArrayList<MyObject>();
myObjects.add(new MyObject("Stack Overflow"));
myObjects.add(new MyObject("Stack Exchange"));
Scanner input = new Scanner(System.in);
System.out.print("What name or partial name would you like to filter? ");
String pattern = input.nextLine();
int count = 0;
for (MyObject i: myObjects) {
if (i.getName().matches(".*" + pattern + ".*")) {
count++;
}
}
System.out.println("Matches: " + count);
Input:
ck
Output:
Matches: 2

Categories

Resources