I have a class called Paragens like this:
public class Paragens {
static int contadorParagens = 1;
String nomeParagem;
int id;
public Paragens(String nomeParagem) {
this.nomeParagem = nomeParagem;
this.id = contadorParagens++;
}
// getters and setters for nomeParagem
}
Every Paragens object has a name and an Id.
This class has a main method where I create several Paragens objects and store them inside an ArrayList like this:
public static void main(String[] args) {
ArrayList<Paragens> paragens = new ArrayList<Paragens>();
paragens.add(new Paragens("name1");
// ... add more paragens
}
This is working ok. If I insert a bunch of paragens and print them I can see tat is all ok.
What I am trying to do is to ask the user to input a paragem name and then I want to see if that paragem is already in the ArrayList.
String name;
System.out.println("Insert paragem name: ");
pickName = sc.nextLine();
System.out.println(paragens.contains(pickName));
What am I doing wrong?
contains checks to see if the list contains the actual thing you handed it. In this case, you're passing in a String name, but comparing it to Paragem instances. contains can't magically guess that it's supposed to look at a given property on the Paragem instances to compare the string.
You can easily loop the list to find out for yourself:
boolean found = false;
for (Paragem p : paragems) {
if (p.nomeParagem.equals(pickName)) { // Or use an accessor function for `nomeParagem` if appropriate
found = true;
break;
}
}
...or as a function:
boolean containsParagemWithName(ArrayList<Paragem> paragems, String pickName) {
for (Paragem p : paragems) {
if (p.nomeParagem.equals(pickName)) {
return true;
}
}
return false;
}
Well, you need to implement the contains method yourself. Do a for loop over the entire array and check if the name of one of the elements is equal with what you're trying to add. If not, add a new Paragens(pickName).
Objects by default are compared by their memory location. So if you have two Paragem with the same name, they are still not equal.
So either, you check the name of each one:
boolean checkDuplicate(String pickName) {
for (Paragem p : paragems) {
if (p.nomeParagem.equals(pickName)) return true;
}
return false;
}
or implement (override) the equals method to compare names (you should be calling contains on a new Paragem object then instead of a String, though).
Related
I'm trying to display Car from fleet ArrayList using user input. Unfortunately I'm not sure how to go about it. I have found few examples online but cannot make them work. I have incorporated following method:
void findRegNo(String reg){
boolean exist=false;
for(int i=0;i<this.fleet.size();i++){
if(this.fleet.get(i).getRegNo() == reg){
exist=true;
break;
}
}
if(exist) {
System.out.println("!!!!!");
} else {
System.out.println("xxx");
}
}
At the moment the result is always: xxx so the code does not find any match. That function is placed in my container class, I was thinking that maybe it supposed to be in different location.
These are variables of Car class:
public class Car {
//defining variables
String regNo;
String model;
double mileage;
Strings are objects, not primitives. Hence, you should use equals to compare their value, not ==, which checks that both references are to the same object:
if (this.fleet.get(i).getRegNo().equals(reg)) {
exist = true;
break;
}
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 want to make a program where you can name a String("weapon" for example)and then add that String to a ArrayList. But without typing it yourself like:
MyArrayList.add(Egg); //for example
So that the new Object automatically add to the Arraylist.
So what I did, I created an Arraylist that will hold the weapon names. I made a method, where you can "make" in the main class a object with the weapon name.But how do i make something that when a object (in the main class)is created, it automatically add it self to the arraylist.
(Sorry for bad explaining, I'm from The Netherlands so... If it's a bad explaining please tell me so i can improve it)
Maybe I completely misunderstand it, but do you want to do something like this?
private ArrayList<YourObject> list;
public YourMainClass(){
list = new ArrayList<YourObject>();
}
public void onAdd(String weaponName){
list.add(new YourObject("weaponName")); // <- this being your issue
}
With YourObject being something like:
public class YourObject
{
private String name;
public YourObject(String n){
setName(n);
}
public void setName(String n){
// Perhaps an if-else to check if n isn't null, nor emtpy?
name = n;
}
public String getName(){
return name;
}
}
Based on my interpretation of your problem, you want to have the user create a weapon name and add it to the ArrayList without having to manually add the code to add it?
A basic way to get String input from a user:
Scanner inputscan = new Scanner(System.in); //reads input from command line
String weapon = inputscan.nextLine(); //waits for user input
MyList.add(weapon);
That way, every time you call the "make" method with that code in it, it will prompt the user to type a weapon name, then the weapon name gets stored in the array.
I think you want to initialize the List with an object in it:
Try using an instance block, like this:
List<String> list = new ArrayList<String>() {{
add("Egg");
}};
Add the command to add the object to the collection in the constructor.( But this ill advise)
You can create an auxiliary class that will create that object and label to the collection.
class WeaponFactory
{
Collection c;
public WeaponFactory(Collection coll){c=coll;}
public Weapon makeWeapon(String text) // Makes sense when the object is not String , like a Weapon class which also contains stats or something
{
Weapon w = new Weapon(text)
c.add(w);
return w;
}
}
class Weapon
{
String name;
public Weapon(String text)
{
name = text;
}
}
I explain what I am trying to do in comments above the parts in the method:
public int addPatron(String name) throws PatronException {
int i = 0;
//1. Iterate through a hashmap, and confirm the new name I am trying to add to the record doesn't already exist in the hashmap
for (Map.Entry<Integer, Patron> entry : patrons.entrySet()) {
Patron nameTest = entry.getValue();
//2. If the name I am trying to add already exists, we want to throw an exception saying as much.
if (nameTest.getName() == name) {
throw new PatronException ("This patron already exists");
//3. If the name is unique, we want to get the largest key value (customer number) already in the hash, an increment by one.
} else if (nameTest.getName() != name) {
Map.Entry<Integer,Patron> maxEntry = null;
for(Map.Entry<Integer, Patron> entryCheck : patrons.entrySet()) {
if (maxEntry == null || entryCheck.getKey() > maxEntry.getKey()) {
maxEntry = entryCheck;
i = maxEntry.getKey();
i++;
}
}
} else {
throw new PatronException("Something's not working!");
}
//4. If everything is ok up to this point, we want to us the name and the new customer id number, and use those to create a new Patron object, which then gets added to a hashmap for this class which contains all the patrons.
Patron newPatron = new Patron(name, i);
patrons.put(i, newPatron);
}
return i;
}
When I try and run a simple unit test that will fail if I successfully add the same name for addPatron twice in a row, the test fails.
try {
testLibrary.addPatron("Dude");
testLibrary.addPatron("Dude");
fail("This shouldn't have worked");
The test fails, telling me the addPatron method is able to use the same name twice.
#Jon Skeet:
My Patron class looks like this:
public class Patron {
//attributes
private String name = null;
private int cardNumber = 0;
//operations
public Patron (String name, int cardNumber){
this.name = name;
this.cardNumber = cardNumber;
}
public String getName(){
return name;
}
public int getCardNumber(){
return cardNumber;
}
}
As others have said, the use of == for comparing strings is almost certainly inappropriate. However, it shouldn't actually have caused a problem in your test case, as you're using the same constant string twice, so == should have worked. Of course, you should still fix the code to use equals.
It's also not clear what the Patron constructor or getName methods do - either of those could cause a problem (e.g. if they create a new copy of the string - that would cause your test to fail, but would also be unnecessary usually).
What's slightly more worrying to me is this comment:
// 3. If the name is unique, we want to get the largest key value (customer number)
// already in the hash, an increment by one.
This comment is within the main loop. So by that point we don't know that the name is unique - we only know that it doesn't match the name of the patron in this iteration.
Even more worrying - and I've only just noticed this - you perform the add within the iteration block too. It seems to me that you should have something more like this:
public int addPatron(String name) throws PatronException {
int maxKey = -1;
for (Map.Entry<Integer, Patron> entry : patrons.entrySet()) {
if (entry.getValue().getName().equals(name)) {
// TODO: Consider using IllegalArgumentException
throw new PatronException("This patron already exists");
}
maxKey = Math.max(maxKey, entry.getKey());
}
int newKey = maxKey + 1;
Patron newPatron = new Patron(name, newKey);
patrons.put(newKey, newPatron);
return newKey;
}
Additionally, it sounds like really you want a map from name to patron, possibly as well as the id to patron map.
You need to use equals to compare String objects in java, not ==. So replace:
if (nameTest.getName() == name) {
with:
if (nameTest.getName().equals(name)) {
Try to use
nameTest.getName().equals(name)
instead of
nameTest.getName() == name
because now you're comparing references and not the value of the String.
it's explained here
Took another look on your code
Well i took another look on your code and the problem is, that your HashMap is empty at the start of the Test. So the loop will never be runned ==> there will never bee a Patron added or an Exception thrown.
The cause of the problem is how you have used the compare operator ==.
When you use this operator against two objects, what you test is that variable point to the same reference.
To test two objects for value equality, you should use equals() method or compareTo if available.
For String class, invoke of equals is sufficient the check that the store same characters more.
What is equals method ?
To compare the values of Object
The problem is how you compare names.
Can Any help me and Check my answer
(a) Declare a private instance variable (Attribute) called HouseMap which should hold an unsorted map with integer keys and string values.
Private Map< Integer, String> HouseMap = new HashMap<Integer, String>();
(b) Write a zero-argument constructor of HouseCatalogue that initializes HouseMap to an empty map.
houseMap = new HashMap<Integer, String>();
(c) Write an instance method called addHouse() for the HouseCatalogue class that takes no arguments, and returns no value. This method should simply enter the four entries shown above into the HouseMap.
Public void addHouse()
{
HouseMap.put(101," adison Sas") ;
HouseMap.put(103," FourSeasons") ;
HouseMap.put(105," Hayat Regency ");
HouseMap.put(107," Concord al-Salam ") ;
}
(d) Write an instance method called printHouse() for the HouseCatalogue class that takes an integer argument, and return a string value. This method should print the value (House name) of the area code that is equal to integer argument and return it. Otherwise it will return null.
Public string printHouse( int area)
{
for(Integer eachcode : HouseMap.keySet())
{
if ( HouseMap.keySet()== area)
{
System.out.println("House name is"+ HouseMap.get(eachcode));
}
}
}
or
public static void printHouse( int area)
{
for(Map.Entry<Integer,String> entry : houseMap.entrySet())
{
if (entry.getKey().equals(area))
{
System.out.println("House name is"+ entry.getValue());
//return entry.getValue(); // return it
}
}
}
(a) Lower case letter for private and no new HashMap() needed when declaring. Normally when useing java convensions you use camelcase when declaring your variasbles (houseMap) but it's fine.
private Map<Integer, String> HouseMap;
(b) You have declared your variable with HouseMap not houseMap (see (a) camelcase) so initializing it needs the same variable:
HouseMap = new HashMap<Integer, String>();
(c) Seems fine
(d) Hum, don't see the point in the method, it should both print the value and return it.. well.. first off public lower case letters again, String with a big letter (name of the class` and then the implementation:
public String printHouse(int area) {
if (HouseMap.containsKey(area)) {
String name = HouseMap.get(area);
System.out.println("The house with the area code " + area +
" is " + name));
return name;
}
return null;
}
a) only declare the variable - do not initialize it
b) ok
c) ok
d) in a map you have random access. look at Map#get(Integer) API. you don't need to iterate over the entry set
Since the key of a map is unique, you can simplify the last method as follows:
public static void printHouse( int area)
{
String name = houseMap.get(area); // May return null
System.out.println("House name is " + name);
return name;
}
public and private must be written with a lowercase p everywhere.
You should show the entire constructor, not just the code that goes in it.
Fix your indentation. Use the same amount of indentation for every level, and make sure that everything lines up neatly.
When you use a foreach loop like for (Integer eachcode: HouseMap.keySet()), the iteration variable is eachcode. This is the value that you should compare to area, because that's what the integer is. You don't want to compare the supplied to all of the area codes taken as a single unit (those aren't the same kind of thing); you want to compare it to each area code in turn.
But you don't want to write that loop at all. The point of a HashMap is to let you look up the value, given the key. That is what .get() does. You have the key: it is area. So all you need to do is look it up: System.out.println("House name is " + HouseMap.get(area)).
You also need to return the name that you looked up, not just print it, and you need to check that the name is there (use .contains()) before printing.
It looks like somebody else commented your code to say "you also forgot to return it". Did you try talking to this person, or reading the comments?
Just a hint for the last one:
(d) Write an instance method called
An instance method is not a static method, you have to remove the static keyword in your second (d) method...
Thanks alot for every body
public static String printHouse(int
code) {
if (houseMap.containsKey(code))
{
String name = houseMap.get(coe);
System.out.println(code+ " : " + name);
return name;
} else{
System.out.println("null");
return null; }