Unable to print desired output while practicing getters setters - java

Besides the get and set method, I created a method called printAllDetails with the purpose to print out details of every registrant. There are 3 registrants with each of their respective names and ages.
public class BASIC_GettersSetters {
String name;
int age;
public static void main(String[] args) {
BASIC_GettersSetters a = new BASIC_GettersSetters(); // Assume BASIC_GettersSetters is Account
a.setName("Kim Hyun Jin");
a.setAge(32);
System.out.println(a.getName());
System.out.println(a.getAge());
a.setName("Kang Jeon Il");
a.setAge(32);
System.out.println(a.getName());
System.out.println(a.getAge());
a.setName("Choi Jin Woo");
a.setAge(30);
System.out.println(a.getName());
System.out.println(a.getAge());
a.printAllDetails();
}
The method is right at the bottom. When I pressed the F6 key to run the program, it only shows the last registrant; Choi Jin Woo, 30. So I'm confused right there. Should I use array? But then, how do I apply it together with get and set methods? Or should I use something else that I don't know of?
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
public void printAllDetails () {
System.out.println("Registrants : " + getName() + " // " + getAge());
}
}
Any help is appreciated. Thank you. - Coding noob

You're creating one instance of BASIC_GettersSetters and repeatedly changing the values. So when you call printAllDetails it's printing the last set of values.
You want to create separate instances:
BASIC_GettersSetters a = new BASIC_GettersSetters();
a.setName("Kim Hyun Jin");
a.setAge(32);
System.out.println(a.getName());
System.out.println(a.getAge());
BASIC_GettersSetters b = new BASIC_GettersSetters();
b.setName("Kang Jeon Il");
b.setAge(32);
System.out.println(b.getName());
System.out.println(b.getAge());
BASIC_GettersSetters c = new BASIC_GettersSetters();
c.setName("Choi Jin Woo");
c.setAge(30);
System.out.println(c.getName());
System.out.println(c.getAge());
a.printAllDetails();
b.printAllDetails();
c.printAllDetails();
You should also consider renaming BASIC_GettersSetters() to something more meaningful.

You create only one object (new BASIC_GettersSetters()). If you call the setter on the same object multiple times, you overwrite the previously set value.
First, you should name your classes properly. I suggest renaming your BASIC_GettersSetters to Registrant. Second, you should create as many Registrant objects as needed (in your case, three).

Related

How to return a parameter on the basis on another parameter in list of object

I have the following InventoryItem class:
#AllArgsConstructor
#Getter
public class InventoryItem {
private String name;
private int amount;
// other properties, getters, etc.
}
And I have an Inventory object that contains a List of InventoryItems.
I want to obtain the amount of the item where the name is equal to the given name.
I am trying to use streams for that purpose:
inventoryItems.stream().filter(item -> item.getName().equals(name));
But it is returning the whole item, I only want the amount. How can I do that?
I am new to java so do not have idea.
Using JDK 14:
I have implemented the below code using records instead of creating POJO's.
Note (As a suggestion): As I can see in your given code, you are using some annotations(#AllArgsConstructor #Getter,..) for auto creation of constructors, getters and setters, so for that boiler-plate code, records seems to be a good option which is available from java 14 onwards.
Records in java : As of JDK 14, we can replace our data classes with records. Records are immutable classes that require only the type and name of fields. We do not need to create constructor, getters, setters, override toString() methods, override hashcode and equals methods.(records javadoc)
Please find the code below:
public class Test {
public static void main(String[] args) {
String nameToFind = "item1";
int amount = 0;
record InventoryItem(String name,int amount){}
Optional<Integer> optional = List.of(new InventoryItem("item1",100),
new InventoryItem("item2",200),
new InventoryItem("item3",300))
.stream().filter(x -> x.name().equals(nameToFind)).map(InventoryItem::amount).findFirst();
if(optional.isPresent()){
amount = optional.get();
}
System.out.println(amount);
}
filter operation is an intermediate operation. We need one of terminal operation to get the result. Below are couple of ways to get the Amount
import java.util.Arrays;
import java.util.List;
class InventoryItem {
String name;
float amount;
public InventoryItem(String name, float amount) {
this.name = name;
this.amount = amount;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getAmount() {
return amount;
}
public void setAmount(float amount) {
this.amount = amount;
}
}
public class ItemAmount {
public static void main(String[] args) {
List<InventoryItem> inventoryItems = Arrays.asList(new InventoryItem("A", 100f), new InventoryItem("B", 50f));
//method-1
float amount = inventoryItems.stream().filter(item -> item.getName().equals("B")).findFirst().get().getAmount();
System.out.println("Amount of B item is: " + amount);
//method-2
List<InventoryItem> matchList = inventoryItems.stream().filter(item -> item.getName().equals("B")).collect(Collectors.toList());
matchList.forEach(i -> System.out.println("Item: " + i.getName() + ", Amount: " + i.getAmount()));
}
}
Use the map() function, append it after the filter.
Optional<int> result = inventoryItems.stream().filter(item -> item.getName().equals(name)).map(item -> item.getAmount()).findFirst();
There are to issues:
Your stream lacks a terminal operation which is needed to obtain the result of the stream execution.
To amount from an InventoryItem you need to apply map() operation.
That's how you can generate a list of amounts that correspond to the items having the given name:
public List<Integer> getAmountsByName(List<InventoryItem> inventoryItems,
String name) {
return inventoryItems.stream()
.filter(item -> item.getName().equals(name))
.map(InventoryItem::getAmount)
.toList(); // for Java 16+ or collect(Collectors.toList()) for earlier versions
}
In case if names of items are expected to be unique, then you can apply findFirst() as a terminal operation, which returns an Optional as a result (because resulting value might not be present).
There are many possibilities how you can dial the Optional, for instance you can use orElse() to provide the default value, or orElseThrow() to throw an exception if a result was not found (sometimes it makes sense to return an Optional, and deal with it in the calling method).
That's how it might look like:
public int getAmountByName(List<InventoryItem> inventoryItems,
String name) {
return inventoryItems.stream()
.filter(item -> item.getName().equals(name))
.map(InventoryItem::getAmount)
.findFirst()
.orElse(-1); // in case if an item with the target name isn't present return zero
// .orElseThrow(); // alternatively you can throw an exception depending on your needs
}

Why doesn't the Fourth Line End With "Arnie"?

I am "learning Java" using a tutorial. One of the lessons involves constructors calling constructors.
After the lesson I did some playing around doing "strange stuff" and I can't figure out what is happening.
I attached an image file captured from the Eclipse screen. (don't be hating).
I thought that would be better because it shows the output screen.
I would expect "name" to be "Arnie" the first time it is printed in the second constructor.
Why is it "Bertie"?
class Machine {
private String name;
private int code;
public Machine() {
this("Arnie", 0);
System.out.println("First constructor running: " + name);
}
public Machine(String name) {
this("Arnie", 0);
System.out.println("Second constructor running before 'this.name': " + name);
this.name = name;
System.out.println("Second constructor running after 'this.name': " + name);
}
public Machine(String name, int code) {
this.name = name;
this.code = code;
System.out.println("Third constructor running: " + name + " " + code);
}
}
public class Application {
public static void main(String[] args) {
Machine machine1 = new Machine();
Machine machine2 = new Machine("Bertie");
Machine machine3 = new Machine("Chalkie", 7);
}
}
It is printing the name variable that is passed in to the constructor. Leaving everything the same, you would see "Artie" if you were to change name to this.name.
The reason is that the constructor that takes the name argument is shadowing the property String name. Either change constructor argument to something other than name, or change lines 12 and 14 to be this.name.

assertEquals() with HashSet

I have a constructor for the class of player
public Player(String name, String playerDescription,
HashSet<String> abilities) {
this.name = name;
this.playerDescription;
this.abilities = abilities;
}
I create an instance of this class
Player p = new Player ("Jon Snow", "Brave Swordsman", new HashSet<String>());
I've created an addAbilities() method, to add to the HashSet.
public void addAbilities(String newAbility) {
abilities.add(newAbility);
}
However, when I go to test the method (using a get method)
public String getAbility() {
String abilityString = abilities.toString();
return abilityString;
}
My test :
#Test
public void testAddAbility() {
Player p = new Player("Jon Snow", "Brave Swordsman", new HashSet<String>());
s.addAbility("Leadership");
assertEquals("Leadership", s.getAbility());
}
I get an difference in the test output.
Comparison failure: expected: <[Leadership]> but was <[[Leadership]]>
My question is, why is there a difference in output and is it good practice to make a HashSet this way?
HashSet.toString() returns a String displaying the elements inside [] (and with , character between them).
So in your assertion you compare Leadership to [Leadership].
This would be ok for the assertion :
assertEquals("[Leadership]", s.getAbility());
But I think that you should rather change the method to retrieve abilities.
Is it a retrieval and formatting method ?
Rename the method in this sense.
Otherwise, keep the Set abstraction and just return the Set as it is :
public Set<String> getAbilities(){
return abilities;
}
The format for a Set toString output is "[item1, item2, ...]". You only have one item, so it's "[item1]".
I'd suggest you make this method
public Set<String> getAbilities()
Or better yet
public Set<Ability> getAbilities()
your code has potentially flaws at a couple of points, the first one is
ability is a collection, so this getter is not correct because it returns a String
public String getAbility() {
String abilityString = abilities.toString();
return abilityString;
}
so that "getter" is giving back a string that java JDK developers can change without even inform anybody... as a concecuense of that
the #test is failing....
you should return a (an unmodifiable) collection in the getter and from that check whether the string value is present...
Set<String> mySet = new HashSet<>();
mySet.add("Leader");
mySet.contains("Leader");
now you are indeendent of what is happening in the future with the toString implementation of the hashSet
I suggest removing the getAbility() method and adding:
public boolean hasAbility(String ability) {
return abilities.contains(ability);
}
as for testing the addition method, you can do this:
#Test
public void testAddAbility() {
Player p = new Player("Jon Snow", "Brave Swordsman", new HashSet<String>());
p.addAbility("Leadership");
assertTrue(p.hasAbility("Leadership"));
}

Java return multiple strings in one method

I am attempting to write a program which asks users what their pet name is, species, finds out thirst level and gives a response accordingly.
I would appreciate if someone could help me with a problem im having, in each of the 2 methods askpetname and thirstlevel there are 2 strings i want accessible throughout the entire class without using global variables.
Can someone tell me what it is i am doing incorrectly or point me in the right direction.
Also, i understand that my excess use of methods for tedious tasks is bad practice but it helps with memorising syntax.
Thanks.
class dinoo
{
public static void main(String[] p)
{
explain();
output();
System.exit(0);
}
public static void explain()
{
print("The following program demonstrates use of user input by asking for pet name.");
return;
}
public static String askpetname()
{
Scanner scanner = new Scanner(System.in);
print("Name your dinosaur pet!");
String petname = scanner.nextLine();
print("Awesome, cool dinosaur name, what species is " + petname+ " ?");
String petspecies = scanner.nextLine();
return petname, petspecies;
}
public static int thirstlevel()
{
Random ran = new Random();
int thirst = ran.nextInt(11);
int hunger = ran.nextInt(11);
return thirst,hunger;
}
public static String anger(int thirst, int hunger)
{
double angerscore = (thirst+hunger)/2;
String temper;
if(angerscore<=2)
{
temper = "Serene";
}
else if(3<=angerscore<=6)
{
temper= "Grouchy";
}
else if(6<angerscore)
{
temper = "DANGEROUS";
}
return temper;
}
public static String warning()
{
if (temper.equals("Serene"))
{
print("He's looking happy!");
}
else if(temper.equals("Grouchy"))
{
print("Ahhh hes a bit "+temper+", you better start feeding him before he gets mad!");
}
else if(temper.equals("DANGEROUS"))
{
print("GET OUT OF THERE, HES " + temper+"!!!. He will have to be put down for everyones safety.");
}
}
public static void output()
{
print(askpetname() + "'s, thirst level is "+thirstlevel()+"/10");
return;
}
public static String print(String message)
{
System.out.println(message);
return message;
}
}
That code won't compile since you can't have:
return string1, string2;
or
else if(3<=angerscore<=6)
Instead of trying to return multiple Strings, your best bet is to create a class, say called Pet, one that holds String fields for the pet's name, a Species field for its species, as well as any other fields for hunger, thirst ... that would best encapsulate all the data that makes up one logical "pet" as well as a methods such as getAnger() that returns a value for anger depending on the Pet's state. Then you can create and return a viable Pet object from your creational method.
Also, your code has lots of compilation errors, suggesting that you could improve the way that you create your code. Never try to add new code to "bad" code, to code that won't compile. If possible, use an IDE such as NetBeans, Eclipse, or IntelliJ to help you create your programs. The IDE's will flag you if any of your code contains compilation errors, and then the key is: don't add new code until you've first fixed the existing compilation error. If you can't use an IDE, then you must compile early and often, and do the same thing -- fix all errors before adding new.
First, I would recommend shooting through a tutorial first before attempting this, do all the hello worlds covering scope, objects, arrays and functions. Get familiar with Object Oriented Style, although thats not even procedural programming ... nothing returns 2 objects ... always 1 (it could be an array containing many objects, but an array is a single object)
Moving on,although this is terrible coding practice, but its ok for a beginner,since your functions are all static, create a private static variable inside each function and create getter functions
//convert
String petname = scanner.nextLine();
// To this
private static String petname = scanner.nextLine();
// Then add this below it
public static String getPetName()
{
return petname;
}
and same for every piece of data you need.
Now remove the return statement from all of your functions and declare return type as void
Then call all functions from Main,
askpetname();
thirstlevel();
then print final output (after you have called the functions) as such
System.out.println("Petname: " + getPetname + " ThirstLevel: " + getThirstLevel() + " HungerLevel: " + getHungerLevel);

Java target/select class/object - confused (sorry for bad title)

What I have below is producing the desired results by print some employee details along with weekly / monthly wages as appropriate.
However I understand that I should not be inputting data in the constructor as I've done.
I need to prompt for a hours worked value only for "PartTimeEmployees", just not the way I've done it.
I've tested with For-Each loops, Enhanced For loops and using the instanceOf operator.
If I could get some guidance/hints or examples of how to accomplish what is currently being done in the constructor, but in the TestEmployee class instead that would be great.
Mostly I'm not sure how to even describe what I'm trying to achieve. This hinders Googling somewhat. (Help with a better title would also be great)
Thanks in advance.
public class TestEmployee
{
public static void main(String[] args)
{
int size;
Employee[] employees = new Employee[4];
employees[0] = new FullTimeEmployee("Jane", 26000);
employees[1] = new PartTimeEmployee("Jack");
employees[2] = new FullTimeEmployee("Lucy", 52000);
employees[3] = new PartTimeEmployee("Lenny");
for(int i = 0; i < employees.length; i++)
{
employees[i].print();
}
}
}
Class: PartTimeEmployee - Constructor:
public PartTimeEmployee(String thisName)
{
super(thisName);
System.out.println("Please enter the number of hours worked by " + thisName + ": ");
numHours = keyboard.nextInt();
setHours(numHours);
}
If I get your question, below might fit with your need -
First of all create generic Employee class -
class Employee {
private String name;
private int workingHours;
private final boolean IS_PART_TIME_EMP;
public Employee(String name, int workingHours) {
this.name = name;
this.workingHours = workingHours;
this.IS_PART_TIME_EMP = false;
}
public Employee(String name) {
this.name = name;
this.IS_PART_TIME_EMP = true;
}
public String getName() {
return name;
}
public int getWorkingHours() {
return workingHours;
}
public void setWorkingHours(int workingHours) {
this.workingHours = workingHours;
}
public boolean isPartTimeEmployee() {
return IS_PART_TIME_EMP;
}
}
Now you can use it as per your requirement.
Employee[] employees = new Employee[4];
employees[0] = new Employee("Jane", 26000);
employees[1] = new Employee("Jack");
employees[2] = new Employee("Lucy", 52000);
employees[3] = new Employee("Lenny");
Scanner sc = new Scanner(System.in);
for (Employee employee : employees) {
if(employee.isPartTimeEmployee()) {
System.out.println("Please enter working hours by " + employee.getName() + ": ");
int numHours = sc.nextInt();
employee.setWorkingHours(numHours);
}
}
Constructor is not meant for user input.Its main intention is to initialize object of that class.
Instead of doing that in constructor,you can try something like this
employees[1] = new PartTimeEmployee("Jack");
System.out.println("Please enter the number of hours worked by " + employees[1].getName()+ ": ");
numHours = keyboard.nextInt();
employees[1].setHours(numHours);
You most likely will have some logical main loop in your program, like
while(!quit) {
// 1. ask if you want to add part time or full time employee
// 2. ask proper questions
// 3. call correct constructor
}
Writing such small pseudo code algorithm should be self explanatory and get you going.
Step one: presentation of options available for user and reading user input.
Step two: performing actions depending on user input from step 1
Step three: final call to proper constructor depending on results from steps 1 and 2
If I understood your question correctly (which I'm really not sure of) you want to prompt for the employee data in the main method.
In that case I'd use a loop and query the following things:
name of the employee
does the employee work full time? (y/n)
if yes: what is the wage? (assume hours = whatever a full time employee works a day)
if no: how many hours? (and probably the hourly wage as well)
Then use that information to construct an Employee object (I don't see any need for the subclasses here).

Categories

Resources