I'm new to OO. I've just started programming in Java for my university course.
I have a problem:
I have a method within the Club class to search for a member's name (or part of a name, according to my worksheet.
I have a class that tests this without me having to manually create objects from the Club class (I'm using BlueJ).
Here's the search method:
public void searchMember(String name){
i=0;
found = false;
while( i < members.size() && !found ){
if(members.contains( name )){
found = true;
}else{
i++;
}
}
if(found == true){
System.out.println(members.get(i));
}else{
System.out.println("Och Naw ... Member not found.");
}
}
And here is the testing class code:
public void demo()
{
club = new Club();
club.join(new Membership("Gordy Broon", 1, 1972));
club.join(new Membership("Eck Salmon", 9, 1965));
club.join(new Membership("Davie Caramel", 5, 1960));
System.out.println("Now doing some searching: ");
club.searchMember( "mon" );
System.out.println(" ");
System.out.println("And some more searching: ");
club.searchMember("moon");
System.out.println(" ");
}
Can someone explain to me why when searching for "mon" the result is not found?
To my understanding this should work.
I am new so ANY help and explanation would be amazing ^_^
Thanks!
You are comparing a String with a Membership. The contains method of List will go through every item in the list and check whether "mon".equals(membership), but a Membership object will presumably never return true that it is equal to some String.
(I am making an assumption about your Membership class, that you have not overridden the equals method from java.lang.Object. It would be possible to override equals so that it does return true when compared with a String, but there are two problems. One, you are expecting not just a match when they are equal, but a substring match (where "mon" matches "Eck Salmon"), and two, implementing equals this way would be a violation of its contract. It is expected that if a.equals(b) then b.equals(a), but no java.lang.String object is ever going to return true that it is equal to one of your Membership objects, and you can't modify java.lang.String to make it do that.)
What you want to do is go through the list and check if any of the membership objects have a name that contains "mon". I assume your Membership object has a getName() method:
for (Membership membership : members) {
if (membership.getName().contains(name)) {
System.out.println(membership);
return;
}
}
System.out.println("Och Naw ... Member not found.");
It is possible to do this a little more tersely in Java 8:
Optional<Membership> maybeMember = membership.stream()
.filter(m -> m.getName().contains(name)).findFirst();
String result = maybeMember.map(m -> m.toString())
.orElse("Och Naw ... Member not found.");
System.out.println(result);
This finds the first item in the list that matches the condition that its name must contain the specified name, and then maps it to a string using its toString method, or else uses the default string if no matching item from the list was found.
It seems that members is a list. So when you do members.contains( name ) it wont work. You beed to do the following members.get(i).getName().contains( name ).
Related
I'm making a "dog register" where you can save information about dogs and bid on dogs up for auction etc.
I am a beginner and was recently told that array list should be private, this information got me in some trouble.
I got a class named Auction where you can store bids, I made a get method in this class to use in the main class. It works on every line except one in my method where you can delete a user.
private void deleteUser()
{
System.out.println("Enter the name of the user: ");
String name = input.nextLine().toLowerCase().trim();
User deleteUser = getUser(name);
while (name.isEmpty()) {
System.out.println("Error. Enter the name of the user: ");
name = input.nextLine().toLowerCase().trim();
deleteUser = getUser(name);
}
if (deleteUser == null) {
userException();
return;
}
for (Auction a : auctionRegister) {
ArrayList<Bid> bids = new ArrayList<>();
for (Bid b : a.getBidList()) {
if (b.getUser() != deleteUser) {
bids.add(b);
}
}
a.getBidList() = bids;
}
if (deleteUser.getDogList() != null) {
for (Dog dog : deleteUser.getDogList()) {
dogRegister.remove(dog);
}
}
userRegister.remove(deleteUser);
System.out.println("User " + deleteUser.getUserName() + " is removed");
}
I get the error message on this line("The left-hand side of an assignment must be a variable"):
a.getBidList() = bids;
Everything worked when i had the array list public so my question is, how do i solve this?
Java has 2 varieties of 'buckets' in which to store information. One variety is a variable, the other is a constant. Both varieties let you look in the bucket to see the contents. A variable also allows you to you replace the current contents of the bucket.
Your syntax , a.setBidList() is a method call, which is constant. You can read from it but you can't assign a new value to it. Since you have it on the left side of an assignment statement, you are asking Java to do something it can't do.
I have this method which takes n number of arguments and search for a book in an arrayList using couple of arguments. .
How can i make it smaller?
How to sort books by category or author?
thank you in advance.
Here is my method
// search for a book using multiple criteria
static void bookSearch(String... varg) { // take varg as parameter
String title = ""; // place holders
String author = "";
if (varg.length > 1) { // check varg length
title = varg[0]; // if it is greater than 1 initialize needed arguments
author = varg[1];
} else {
title = varg[0]; // else initialize the first argument
}
for (Book book : bookList) {
/*
* if the title is the same and there is a second argument that
* match author's name print found it
*/
if (book.getTitle().equals(title)) {
if (author.isEmpty() ^ (book.getAuthor().getfName() == author)) {
System.out.println(" \"" +
title +
"\" founded at: " +
bookList.indexOf(book));
break;
}// end of if
} else if (bookList.indexOf(book) == bookList.size() - 1) {// if not found
System.out.println("cant find \"" + title);
}// end of else
} // end of for loop
} //end of search method
In Java8 you can use lambdas and functions to get flexible filter book function.
E.g. you have following Book class:
class Book {
private String author;
private String title;
}
The book filter function could look like this:
BiFunction<List<Book>, Predicate<Book>, List<Book>> BOOK_FILTER =
(books, fields) -> books.stream().filter(fields).collect(Collectors.toList());
Then, all you need is just build required Predicate and use this function.
public static List<Book> findBookByPredicate(List<Book> books, String author, String title) {
Predicate<Book> byAuthor = book -> book.getAuthor().equals(author);
Predicate<Book> byTitle = book -> book.getTitle().equals(title);
return BOOK_FILTER.apply(books, byAuthor.and(byTitle));
}
As you can see, you're not limited only certain number of Book fields. You can combine it as you like; BOOK_FILTER function stays the same.
You can default title to varg[0] and set author if varg.length is greater than one with a ternary. I would prefer a standard loop with a index counter (since otherwise you must search again to determine the index). Next, you need to complete the loop before declaring the title isn't found (I would use a boolean to maintain that state). Next, you logically need an or (not a xor) to check that the author argument is present and not empty before checking the book author. I would prefer formatted io. Like,
static void bookSearch(String... varg) {
String title = varg[0], author = varg.length > 1 ? varg[1] : "";
boolean found = false;
for (int i = 0; i < bookList.size(); i++) {
Book book = bookList.get(i);
if (book.getTitle().equals(title)
&& (author.isEmpty() || book.getAuthor().getName().equals(author))) {
System.out.printf("\"%s\" found at: %d%n", title, i);
found = true;
break;
}
}
if (!found) {
System.out.printf("cant find \"%s\"%n", title);
}
}
You can use java 8 lamda expression for this.
Ex.
List<String> lines = Arrays.asList("spring", "node", "mkyong");
//Here pass your collection and filter as per your requirement
List<String> result = lines.stream()
.filter(line -> !"mkyong".equals(line))
.collect(Collectors.toList());
Aside from using lambda expression, other way to make your code a little shorter would be to implement equals method for your Book class where you can compare two Book objects for equality by their title and author. Then instead of:
if (book.getTitle().equals(title)) {
if (author.isEmpty() ^ (book.getAuthor().getfName() == author)) {
System.out.println(" \"" + title + "\" founded at: "
+ bookList.indexOf(book));
break;
}// end of if
you can just use:
Book searchForBook = new Book();
searchForBook.setAuthor(author); //ins
searchForBook.setTitle(title);
for (Book book : bookList) {
if (book.equals(searchForBook)){
System.out.println(" \"" + title + "\" found at: "
+ bookList.indexOf(book));
break;
}
You can also make the creation of object searchForBook one line only, if you add proper constructors in your Book class.
On sorting the ArrayList - you can either make Book implement Comparable and use Collections.sort(bookList) or use a Comparator instead and use Comparator and again use Collections.sort before you use the collection, to have it sorted the way you want.
Your code can be shortened like this:
static void bookSearch (String... varg) {
String author = "";
String title = varg[0];
if (varg.length > 1) {
author = varg[1];
}
for (Book book : bookList) {
if (book.getTitle().equals (title)) && (author.isEmpty() || (book.getAuthor().getfName() == author)) {
System.out.println(" \"" + title + "\" founded at: " + bookList.indexOf(book));
return;
}
}
System.out.println("cant find \"" + title);
}
Title doesn't need to be in if and else branch. Just initialize on declaration.
Take the ternary operator from Elliot if you like
Your outer if only has the inner if (title/author). This can be replaced by &&.
Just return instead of breaking.
With the premature return, you don't need else anymore.
A boolean predicate 'matches' which does the same thing in the Book class might be preferred. Sorting can be a good idea, if you don't have to resort by different criteria often and if you search for multiple books - then it can pay off.
A boolean return or a return of the index, where the book was found, might be more flexible. But for reporting the index, I would use a classical for loop, where you get it by the same iteration.
Returning the index would allow to remove the System.outs, so that the caller can decide, how to handle the event: Order a book via net, print to stdout, output with Swing oder JavaFX or whatever.
A pure compareTo would allow efficient search algorithms to find many book in big lists fast and smooth integration in the new Stream collections.
Using varg seems to be a bad idea to me, since it opens the door wide for getting the parameter order wrong.
int bookSearch (String title, Optional[String] author) {
expresses more clearly what you want - many IDEs support parameter names.
I've been working on a problem:
"Design a program that asks the user for a series of names (in no particular order). After the final person’s name has been entered, the program should display the name that is first alphabetically and the name that is last alphabetically.
For example, if the user enters the names Kristin, Joel, Adam, Beth, Zeb, and Chris, the program would display Adam and Zeb."
I have a function called getString, which returns a valid string input; and a module called displayResults, which displays the first name alphabetically, and last name alphabetically. I also use "q" as a sentinel value to exit the while loop.
However, I am running into a problem where if I enter in names such as: "bob", "david", "alex", and "charlie", it will display the first name correctly as "alex", but will display the last name incorrectly as "charlie" instead of "david". I've tried looking through my code for an error, but wasn't able to locate where it's messing up. Any help is appreciated.
name = getString("Please enter a name, or input q to exit.");
if(!name.equals("q")) {
low = name;
high = name;
}
while(!name.equals("q")) {
int x;
x = name.compareToIgnoreCase(low);
if(x == -1){
low = name;
}
x = name.compareToIgnoreCase(high);
if(x == 1) {
high = name;
}
name = getString("Please enter another name, or input q to exit.");
}
displayResults(low, high);
The Java API documentation only states that compareToIgnoreCase() "Returns:
a negative integer, zero, or a positive integer". Since you are comparing x to 1 and -1 respectively it is possible you are actually receiving another value back and therefore the true "high" is not being detected.
Another possibility is that there may be invisible characters (like space or return) in your input. When I ran " david".compareToIgnoreCase("charlie") on my machine here it returned -67.
You could use a List which you sort then.
import java.util.List;
import java.util.Collections;
public class Main {
public static void main (String[] args) {
boolean run = true;
List<String> names = new List<String>();
while (run) {
String name = getString ();
if (name == "q") run = false;
else
names.add (name);
}
Collections.sort (names);
// Results:
System.out.println (names.get (0)); // Print out first entry
System.out.println (names.get (names.size() - 1)); // ... and last one
}
public static String getString () {
// Your method
}
}
In order to sort names you should use a collection that sorts the elements as you put them in.
For this porpose you can use the TreeSet implementation which is a sorted Set. Set also makes sure that no repeating elements are stored (for this it uses the compareTo method of the elements).
Also you can create a Collator object (which implements the comparator interface), which can use a locale object to sort the elements. It's easy to do localization based sorting with this method.
Please see the example below:
public static void main(String[] args) {
// Create the locale object
// This will be used when sorting the elements
Locale myLocale = Locale.ENGLISH;
// Locale myLocale = new Locale("HU", "hu");
// Locale myLocale = Locale.getDefault();
// Create the collator which will be responsible for using the locale object in order to compare the elements in the TreeSet
Collator coll = Collator.getInstance(myLocale);
coll.setStrength(Collator.PRIMARY);
// TreeSet for storing the elements
// Note that the TreeSet is instantiated with the collator object
TreeSet<String> names = new TreeSet<>(coll);
names.add("bob");
names.add("david");
names.add("alex");
names.add("charlie");
// You can call first and last method to get the first and last element sorted
System.out.println(names.first());
System.out.println(names.last());
}
I think this is the easiest, fastest, and most professional way of sotring elements since in this case you let java do the sorting for you, you only need to configure the way it should do it.
I hope this will be useful.
The searchDatabase method will accept a query string and search the ArrayList to see if the object contains the query(your search should be case-insensitive!) as the name or is of that object type (Hint: use instanceof to check for object type). It will return an ArrayList containing all of the values whose objects contain the query string.
I need to see if the query is the same as a class name (Such as Don/Talent/Overseer) and if it is then I print all objects of that type. If it's equal to a name in one of the objects then I just print that object out. I am confused as to what to do from here. I am looping through all goons in the Database and checking if they are instances of Don/Overseer/Talents and if they are then checking if the user query is equal to the object type and if it is print all of those objects but if it isn't then checking if it's equal to the name of any objects of type "Dom" in the arraylist.
protected ArrayList<Goon> searchDatabase(String query)
{
ArrayList<Goon> clone = new ArrayList<Goon>();
for(Goon a : goonDB)
{
if(a instanceof Don)
{
if(query.equalsIgnoreCase("don"))
{
}
else
{
if(a.getName().equals(query))
{
}
}
}
else if(a instanceof Overseer)
{
}
Your problem statement is ambiguous, here are my assumptions:
Goon is a parent class of Don/Talent/Overseer (They extend/implement
it).
You accept a query which stands for either object or a name
property in one of the implementation classes.
If query is a type name: return all objects of that type in a list.
Otherwise, check if it matches a name property: return all objects that have the same name property. (Although you said print that one object, I am going to ignore that, because then I would be returning null and more requirement questions arise)
I don't want to write it the code for you, because this looks like a homework assignment and you are much better off struggling a bit, but here is a logic that you would need to use to follow above assumptions:
I would first check if query is Don/Talent/Overseer. If it is then go through the list and add all objects that are of that type (instanceof) to your clone list . If it isn't, then go through the whole list and add those that have the name matching the query. Return the list.
Although I see you've already figured it out. I still want to post my answer :P (or else I made it for nothing). Maybe others who have the same problem can use it. I asumed that Don and Overseer implemented Goon by the way. And as a solution I just looped over the database checking if the query and the class name matched.
I also added a little main method to test the search code. And as you can see in the output only the Don's are printed.
package stackoverflow.question_26510341;
import java.util.ArrayList;
import java.util.Iterator;
public class Search {
static ArrayList<Goon> goonDB = new ArrayList<Goon>();
public static void main(String[] args){
goonDB.add(new Don());
goonDB.add(new Don());
goonDB.add(new Overseer());
ArrayList<Goon> list = searchDatabase("Don");
for(int i = 0; i < list.size(); i++){
System.out.println(list.get(i));
}
}
protected static ArrayList<Goon> searchDatabase(String query){
ArrayList<Goon> clone = new ArrayList<Goon>();
Iterator<Goon> iterator = goonDB.iterator();
Goon temp;
while(iterator.hasNext()){
if(query.equals("Don") && (temp = iterator.next()) instanceof Don){
clone.add(temp);
}else if(query.equals("Overseer") && (temp = iterator.next()) instanceof Overseer){
clone.add(temp);
}//etc...
}
return clone;
}
private static interface Goon{
}
private static class Overseer implements Goon{
}
private static class Don implements Goon{
}
}
I have included a block of code below that I just cannot seem to figure out what I am doing wrong. The code is part of a program that I am writing that populates an array list with virtual gas station objects containing several explicit parameters; one of which is a "description" that is a String parameter being the name of the gas station. The method in question, findStation(), takes an explicit parameter that is set to the name of a gas station. Then, using this I search through my array list looking for a gas station description(using a previously declared getDescription() method that I know functions correctly) that matches my toMatch explicit parameter. If a match is found, the integer position in which it is found is returned.
Well, I feel as if I have properly written the code, but when I attempt to do a Junit test on it, I get the error "Expected <6>, but returned <-1>". Does anyone see anything immediately wrong with either my method syntax or the way I am testing the method? Thanks in advance for all the help from you wonderful people!
By the way, I have tried to include everything that pertains to figuring out the specific method in question. Let me know if something else is needed!
Method in question: I create a temporary Station object to hold the information found at the "i" position in the list. Then, I create a temporary String to hold my description from the object I just retrieved. If the description matches the explicit parameter that is input, then I want it to return the index number at which it is found. My constant variable NO_MATCH is set equal to "-1", so my test is telling me that the gas station description does not exist when it clearly does.
public int findStation(String toMatch)
{
//returns the index where a match is found
for (int i = 0; i < stations.size(); i++)
{
Station tmpStation = stations.get(i);
String tmpDescription = tmpStation.getDescription();
if (tmpDescription.equals(toMatch))
{
return i;
}
}
return NO_MATCH;
}
Also, the addStation() method used to add stations.
public boolean addStation(double inLatitude, double inLongitude,
String inDescription, double inPrice, String inFuelType)
{
// Be sure inDescription is not a description in the collection
if (this.findStation(inDescription) == NO_MATCH)
{
Station tmpStation = new Station();
stations.add(tmpStation);
return true;
}
else return false;
}
Junit test including the setup() to give you an idea of what I'm working with.
protected void setUp()
{
// collection for testing
collection2 = new StationCollection();
// add stations to the collection
this.collection2.addStation(39.933611, -82.4725,
"Snake on the Lake", 2.99, "B80");
this.collection2.addStation(39.9621, -83.0005,
"Snake Central", 2.25, "E45");
this.collection2.addStation(39.94, -82.48,
"Snake Brothers", 2.27, "E45");
this.collection2.addStation(39.8614, -82.8916,
"Anna Conda Oil", 2.71, "PROPANE");
this.collection2.addStation(39.8614, -82.8916,
"Anna Conda Oil - II", 2.27, "E45");
this.collection2.addStation(39.9060, -82.7562,
"Tiger Snake", 2.31, "E40");
this.collection2.addStation(39.9611, -82.9988,
"Rattler Ray's", 2.15, "E84");
this.collection2.addStation(40.011792, -82.973196,
"Water Adder Oil", 3.20, "B80");
this.collection2.addStation(40.011792, -82.974,
"Water Adder Oil - II", 2.31, "E40");
}
public void testFindStation()
{
// Create an empty collection
StationCollection collection1 = new StationCollection();
// Attempt to find a station in the empty collection
assertEquals(StationCollection.NO_MATCH, collection1.findStation("Rattler Ray's"));
// Use non-empty collection2
// Look for position of matching station
assertEquals(6, collection2.findStation("Rattler Ray's"));
// Check that it detects a non-matching station
assertEquals(StationCollection.NO_MATCH, collection2.findStation("Sam Snake's"));
}