Using polymorphism to print out string occurrences - java

I having trouble figuring out how to print out how many times "Dr" titles appear in my array objects in my tester program as they contain more than one string. Is using the equals class the best way to approach this?
Note: I am using inheritance and polymorphism.
public class Driver {
public static void main(String[ ] args) {
Person[] persons = new Person[5];
persons[0] = new Person("John Smith");
persons[1] = new Person();
persons[2] = new TitledPerson("Rowan Bean", "Mr");
persons[3] = new TitledPerson("Phil McGraw", "Dr");
persons[4] = new TitledPerson("Hugo Strange", "Dr");
System.out.println("Person 3 and 4 are equal: " + persons[2].equals(persons[3]));
System.out.println();
String search = "Dr";
int counter = 0;
for(int i = 0; i < persons.length; i++) {
System.out.println(persons[i]);
if(persons[i] instanceof TitledPerson) {
if(persons[i].equals(search)) {
counter++;
}
}
}
System.out.println();
System.out.println("There are " + counter + " 'Dr' titles listed.");
}
}
Person Class:
public class Person {
private String name;
private final static String DEFAULT_NAME = "N/A";
public Person() {
this(DEFAULT_NAME);
}
public Person(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public String toString() {
return "Name: " + name;
}
public boolean equals(Object obj) {
if(obj instanceof Person) {
Person otherPerson = (Person) obj;
return name.equalsIgnoreCase(otherPerson.getName());
} else {
return false;
}
}
}
TitledPerson Class:
public class TitledPerson extends Person {
private String title;
public TitledPerson() {
}
public TitledPerson(String name, String title) {
super(name);
this.title = title;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
#Override
public String toString() {
String parentString = super.toString();
parentString += ", " + title;
return parentString;
}
#Override
public boolean equals(Object obj) {
if(obj instanceof TitledPerson) {
TitledPerson otherPers = (TitledPerson) obj;
return super.equals(obj) && this.title.equalsIgnoreCase(otherPers.title);
} else {
return false;
}
}
}

Change to using getTitle from your TitledPerson class while comparing with the search keyword.
if(((TitledPerson)persons[i]).getTitle().equals(search)) {
counter++;
}

The equals method in TitledPerson calls super class equals which will cause the name and title must be the same for equality.
I think the correct implementation of equals in TitledPerson should be
#Override
public boolean equals(Object obj) {
if(obj instanceof TitledPerson) {
TitledPerson otherPers = (TitledPerson) obj;
return this.title.equalsIgnoreCase(otherPers.title);
} else {
return false;
}
}

you seem to do this :
if(persons[i] instanceof TitledPerson) {
if(persons[i].equals(search)) {
counter++;
}
person is object with a name and a title
search on the other hand, is a string
so you need to do this :
if(persons[i] instanceof TitledPerson) {
if(persons[i].title.equals(search)) {
counter++;
}

Related

How to return the string equivalent of an enum value

I'm trying to implement this enum into my program so that it will return the String equivalent of the enum value. So for example, if the value of dept = 3, then it will return Printed Books & eBooks.
This is what I have so far and it doesn't seem to work because when I go to my program tester class and I try to add a new OrderItem it says that the constructor is undefined once I enter an integer from 0-5 for the Department part of the constructor.
Does anyone have any ideas about what I am doing wrong?
The enum
public enum Department {
ELECTRICAL(0), PHOTOGRAPHIC(1), COMPUTING(2), BOOKS(3), MUSIC(4), FASHION(5);
private int dNum;
private static String dept[] = { "Electrical & Electronics", "Cameras & Photography", "Laptops, Desktops & Consoles",
"Printed Books & eBooks", "MP3 & CD Music", "Fashion & Accessories" };
private Department(int num) {
dNum = num;
}
public String toString() {
return dept[dNum];
}
}
The program
public class OrderItem {
private int itemCode;
private String itemName;
private String itemSupplier;
private double itemCost;
private Department dept;
private static int nextCode = 1;
public OrderItem(String itemName, String itemSupplier, double itemCost, Department dept) {
setItemName(itemName);
setItemSupplier(itemSupplier);
setItemCost(itemCost);
setDepartment(dept);
}
public void setItemName(String itemName) {
if (itemName != null) {
this.itemName = itemName;
} else {
if (this.itemName == null)
// a default value
this.itemName = "Unknown";
}
}
public void setItemSupplier(String itemSupplier) {
if (itemSupplier != null) {
this.itemSupplier = itemSupplier;
} else {
if (this.itemSupplier == null)
// a default value
this.itemSupplier = "Unknown";
}
}
public void setItemCost(double itemCost) {
this.itemCost = itemCost;
}
public void setDepartment(Department dept) {
this.dept = dept;
}
public void setDepartment(int dept) {
if (dept == 0)
setDepartment(Department.ELECTRICAL);
else if (dept == 1)
setDepartment(Department.PHOTOGRAPHIC);
else if (dept == 2)
setDepartment(Department.COMPUTING);
else if (dept == 3)
setDepartment(Department.BOOKS);
else if (dept == 4)
setDepartment(Department.MUSIC);
else if (dept == 5)
setDepartment(Department.FASHION);
}
public String getItemName() {
return this.itemName;
}
public String getItemSupplier() {
return this.itemSupplier;
}
public double getItemCost() {
return this.itemCost;
}
public String getDepartment() {
return dept.toString();
}
public int useNextCode() {
itemCode = nextCode;
nextCode++;
return itemCode;
}
public String getDetails() {
String result = "Item name: " + getItemName() + "\n Supplier: " + getItemSupplier() + "\n Department: "
+ getDepartment() + "\n Cost: " + getItemCost();
return result;
}
public String toString() {
System.out.println("Item Code: " + useNextCode());
return getDetails();
}
}
You cannot pass Integer (0-5) in your OrderItem Constructor. Instead you need to pass the desired enum. This should work fine.
OrderItem oi = new OrderItem("PenDrive","HP",300.0, Department.ELECTRICAL);
As the title question was how to return the String value for enum, the answer could be to refactor the enum to have description field instead of inner static array of strings, and add a method to retrieve Department by the ordinal value:
public enum Department {
ELECTRICAL("Electrical & Electronics"),
PHOTOGRAPHIC("Cameras & Photography"),
COMPUTING("Laptops, Desktops & Consoles"),
BOOKS("Printed Books & eBooks"),
MUSIC("MP3 & CD Music"),
FASHION("Fashion & Accessories");
private String description;
private Department(String description) {
this.description = description;
}
public String toString() {
return this.description;
}
public static Department byNum(int ordinal) {
if (ordinal < ELECTRICAL.ordinal() || ordinal > FASHION.ordinal()) {
return null; // or throw IllegalArgumentException
}
return Department.values()[ordinal];
}
}
Then method OrderItem::setDepartment(int dept) may be changed like this (instead of multiple if statements):
public static void setDepartment(int dept) {
Optional.ofNullable(Department.byNum(dept))
.ifPresent(OrderItem::setDepartment);
}

Efficient way to access/store data instead of having a huge constructor class

I'm currently in need of some guidance. Instead of making a huge constructor class with gets/sets. Is it possible to simplify this task?
Trying to avoid having a huge constructor with gets/sets. So I'm assuming what's a good way to avoid doing something like this. How can this sort of thing be simplified significantly?
public User(int id, String name, long skillPoints) {
this.id = id;
this.name = name;
this.skillPoints = skillPoints;
this.level = 0;
// So on so forth
}
Have you heard of Project Lombok?
By adding the annotation #Data you will get a shortcut for #ToString, #EqualsAndHashCode, #Getter on all fields, #Setter on all non-final fields, and #RequiredArgsConstructor. And there are plenty more annotations you can check out!
With Lombok
import lombok.AccessLevel;
import lombok.Setter;
import lombok.Data;
import lombok.ToString;
#Data public class DataExample {
private final String name;
#Setter(AccessLevel.PACKAGE) private int age;
private double score;
private String[] tags;
#ToString(includeFieldNames=true)
#Data(staticConstructor="of")
public static class Exercise<T> {
private final String name;
private final T value;
}
}
Vanilla Java
import java.util.Arrays;
public class DataExample {
private final String name;
private int age;
private double score;
private String[] tags;
public DataExample(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
void setAge(int age) {
this.age = age;
}
public int getAge() {
return this.age;
}
public void setScore(double score) {
this.score = score;
}
public double getScore() {
return this.score;
}
public String[] getTags() {
return this.tags;
}
public void setTags(String[] tags) {
this.tags = tags;
}
#Override public String toString() {
return "DataExample(" + this.getName() + ", " + this.getAge() + ", " + this.getScore() + ", " + Arrays.deepToString(this.getTags()) + ")";
}
protected boolean canEqual(Object other) {
return other instanceof DataExample;
}
#Override public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof DataExample)) return false;
DataExample other = (DataExample) o;
if (!other.canEqual((Object)this)) return false;
if (this.getName() == null ? other.getName() != null : !this.getName().equals(other.getName())) return false;
if (this.getAge() != other.getAge()) return false;
if (Double.compare(this.getScore(), other.getScore()) != 0) return false;
if (!Arrays.deepEquals(this.getTags(), other.getTags())) return false;
return true;
}
#Override public int hashCode() {
final int PRIME = 59;
int result = 1;
final long temp1 = Double.doubleToLongBits(this.getScore());
result = (result*PRIME) + (this.getName() == null ? 43 : this.getName().hashCode());
result = (result*PRIME) + this.getAge();
result = (result*PRIME) + (int)(temp1 ^ (temp1 >>> 32));
result = (result*PRIME) + Arrays.deepHashCode(this.getTags());
return result;
}
public static class Exercise<T> {
private final String name;
private final T value;
private Exercise(String name, T value) {
this.name = name;
this.value = value;
}
public static <T> Exercise<T> of(String name, T value) {
return new Exercise<T>(name, value);
}
public String getName() {
return this.name;
}
public T getValue() {
return this.value;
}
#Override public String toString() {
return "Exercise(name=" + this.getName() + ", value=" + this.getValue() + ")";
}
protected boolean canEqual(Object other) {
return other instanceof Exercise;
}
#Override public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof Exercise)) return false;
Exercise<?> other = (Exercise<?>) o;
if (!other.canEqual((Object)this)) return false;
if (this.getName() == null ? other.getValue() != null : !this.getName().equals(other.getName())) return false;
if (this.getValue() == null ? other.getValue() != null : !this.getValue().equals(other.getValue())) return false;
return true;
}
#Override public int hashCode() {
final int PRIME = 59;
int result = 1;
result = (result*PRIME) + (this.getName() == null ? 43 : this.getName().hashCode());
result = (result*PRIME) + (this.getValue() == null ? 43 : this.getValue().hashCode());
return result;
}
}
}
Add Kotlin to your project, is becoming the standard, solves your problem as a charm, and as is officially supported by Google, you do not have any problem if you go in production, instead to use other libraries( that could have bugs).
Do not think that you cannot manage to transform all the project from Java to Kotlin, because Kotlin is 100 per cent compatible. One of the K features of Kotlin is just to solve your problem: avoiding to have constructor linked to instance variables and getter and setter, is a lot of boiler plate code.
you just add Kotlin to your project, will take less than 3 minutes, then you can change only the POJO classes, this is the name/acronym of the plain classes you are referring with constructors, getter and setters.
After you installed Kotlin, use Data Classes
in this way a class with 86 lines like the following will become one line. Is worthy to do it, even if you are not going to implement Kotlin to the rest of your project
public class Movie {
private String name;
private String studio;
private float rating;
public Movie(String name, String studio, float rating) {
this.name = name;
this.studio = studio;
this.rating = rating;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getStudio() {
return studio;
}
public void setStudio(String studio) {
this.studio = studio;
}
public float getRating() {
return rating;
}
public void setRating(float rating) {
this.rating = rating;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + Float.floatToIntBits(rating);
result = prime * result + ((studio == null) ? 0 : studio.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Movie other = (Movie) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (Float.floatToIntBits(rating) != Float.floatToIntBits(other.rating))
return false;
if (studio == null) {
if (other.studio != null)
return false;
} else if (!studio.equals(other.studio))
return false;
return true;
}
#Override
public String toString() {
return "Movie [name=" + name + ", studio=" + studio + ", rating=" + rating + "]";
}
}
will become just
this and will get for free also toHash and toString:
data class Movie(var name: String, var studio: String, var rating: Float)

Created add() method to insert objects into an array and all i get are null values

this is a class called Doglist to add the object to an array.
public class DogList {
private int numItems;
private DogItem[] dogListArray;
private int position;
DogList () {
numItems=0;
position = 0;
dogListArray = new DogItem[10];
}
public void add (DogItem item) {
dogListArray[numItems++]= new DogItem(item.getName(),
item.getBreed(),
item.getWeight(),
item.getOwner1(),
item.getOwner2()
);
}
public String toString() {
String result = "";
for (int i=0; i<numItems; i++) {
result += dogListArray[i].toString() + "\n";
}
return result;
}
public DogItem searchForDogItem (DogItem gi) {
System.out.println("Here is your obj value: " + gi );
return null;
}//This is the one im having trouble with.
}
I have all the setters and getters in the DogItem class.
and this is from the UI where i get the dog info(name, breed, weight, owners1&2 names)
public void searchForItem (String name ) {
DogItem gi = new DogItem (name);
gi = gl.searchForDogItem(gi);
if (gi==null) {
msgTextField.setText("Dog Not Found");
} else {
nameTextField.setText(String.valueOf(gi.getName()));
breedTextField.setText(String.valueOf(gi.getBreed()));
weightTextField.setText(String.valueOf(gi.getWeight()));
owner1TextField.setText(String.valueOf(gi.getOwner1()));
owner2TextField.setText(String.valueOf(gi.getOwner2()));
}
}
Ill try and clear things up as i go.
this is the output i get
Here is your obj value: null null 0.0 null null
Ok so here is what it probably should look like instead. Just from what I saw wrong already. However you'd probably want to override the toString() method of DogItem.
Main method example of this:
public class Main {
public static void main(String[] args) {
DogItem dogItem = new DogItem("Spot", "Dalmation", "45", "Bob", "Sandy");
DogItem.add(dogItem);
DogItem result = DogItem.searchForItem("Spot");
if (result == null) {
System.out.println("Dog not found");
// GUI error output goes here
} else {
System.out.println("Here is your obj value: " + result);
// Where your GUI stuff goes
}
}
}
DogItem example of this:
public class DogItem {
private static DogItem[] dogListArray = new DogItem[100];
private static int numItems = 0;
private String name;
private String breed;
private String weight;
private String owner1;
private String owner2;
public DogItem(String name, String breed, String weight, String owner1, String owner2) {
this.name = name;
this.breed = breed;
this.weight = weight;
this.owner1 = owner1;
this.owner2 = owner2;
}
public static void add(DogItem dogItem) {
dogListArray[numItems++] = dogItem;
}
public static DogItem searchForItem(String name) {
DogItem dogItem = null;
for (DogItem result : dogListArray) {
if (result != null) {
if (result.getName() == name) {
dogItem = result;
}
}
}
return dogItem;
}
#Override
public String toString() {
String result = name + ", " + breed + ", " + weight + ", " + owner1 + " " + owner2;
return result;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getBreed() {
return breed;
}
public void setBreed(String breed) {
this.breed = breed;
}
public String getWeight() {
return weight;
}
public void setWeight(String weight) {
this.weight = weight;
}
public String getOwner1() {
return owner1;
}
public void setOwner1(String owner1) {
this.owner1 = owner1;
}
public String getOwner2() {
return owner2;
}
public void setOwner2(String owner2) {
this.owner2 = owner2;
}
}
These would be recommended changes from me though:
private static ArrayList<String> owners;
private static ArrayList<DogItem> dogsList;
public DogItem(String name, String breed, String weight, String owner) {
this.name = name;
this.breed = breed;
this.weight = weight;
this.owners.add(owner);
}
public void init() {
owners = new ArrayList<String>();
dogsList = new ArrayList<DogItem>();
}
public void addDog(DogItem dogItem) {
dogsList.add(dogItem);
}
public DogItem searchForItem(String name) {
DogItem dogItem = null;
for (DogItem result : dogsList) {
if (result != null) {
if (result.getName() == name) {
dogItem = result;
}
}
}
return dogItem;
}
public void addOwner(String owner) {
owners.add(owner);
}
public String getOwner() {
return owners.get(owners.size() - 1);
}

GWT mix two objects in my TreeViewModel

I Have this Model :
1) Team :
public class Team {
private String nom ;
private Employee leader ;
private List<Employee> members = new ArrayList<Employee>();
private List<Person> persons = new ArrayList<Person>();
public Team() {
}
public Team(String nom, Employee leader, List<Employee> members, List<Person> persons) {
this.nom = nom;
this.leader = leader;
this.members = members;
this.persons = persons;
}
public Team(String nom) {
this.nom = nom;
}
public Employee addEmployee (Employee employee) {
members.add(employee);
return employee;
}
public Person addPerson (Person person) {
persons.add(person);
return person;
}
public List<Person> getPersons() {
return persons;
}
public void setPersons(List<Person> persons) {
this.persons = persons;
}
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
public Employee getLeader() {
return leader;
}
public void setLeader(Employee leader) {
this.leader = leader;
}
public List<Employee> getMembers() {
return members;
}
public void setMembers(List<Employee> members) {
this.members = members;
}
#Override
public String toString() {
return "Team{" +
"nom='" + nom + '\'' +
", leader=" + leader +
", members=" + members +
'}';
}
public Team(int i){
this.setNom("team"+i);
this.setLeader(new Employee("MoMo" + i, "dd" + i));
this.addEmployee(new Employee("mehdi" + i, "dd" + i));
this.addEmployee(new Employee("albert" + i+1,"dd"+ i));
this.addEmployee(new Employee("lolo" + i+2,"dd"+ i));
this.addPerson(new Person("Person" + i));
this.addPerson(new Person("Person" + i+1 ));
this.addPerson(new Person("Person" + i+2 ));
}
2)
public class Employee {
private String cin;
private String nom;
private String prenom;
3)
public class Person {
private String address;
private String name;
public Person(){
}
public Person(String name) {
this.name = name;
}
public Person(String name, String address) {
this.name = name;
this.address = address;
}
public String getAddress() {
return address;
}
public String getName() {
return name;
}
}
I want to build a GWT TreeViewModel like the following :
Team => (i want to have my list of persons and my list of employees mixed)
Here is my TreeViewModel
public class EmployeeTreeModel implements TreeViewModel {
private final List<Team> teamList;
private final SingleSelectionModel<Employee> selectionModel
= new SingleSelectionModel<Employee>();
public EmployeeTreeModel() {
teamList = new ArrayList<Team>();
{
for (int i = 0; i < 5 ; i++) {
teamList.add(new Team(i) );
}
}
}
#Override
public <T> NodeInfo<?> getNodeInfo(T value) {
if (value == null) {
ListDataProvider<Team> dataProvider
= new ListDataProvider<Team>(teamList);
Cell<Team> cell = new AbstractCell<Team>() {
#Override
public void render(Context context, Team value, SafeHtmlBuilder sb) {
if (value != null) {
sb.appendHtmlConstant(" ");
sb.appendEscaped(value.getNom());
}
}
};
return new DefaultNodeInfo<Team>(dataProvider, cell);
}
else if (value instanceof Team) {
ListDataProvider<Employee> dataProvider
= new ListDataProvider<Employee>(
((Team) value).getMembers());
Cell<Employee> cell =
new AbstractCell<Employee>() {
#Override
public void render(Context context, Employee employee, SafeHtmlBuilder sb) {
if (employee != null) {
sb.appendHtmlConstant(" ");
sb.appendEscaped(employee.getNom());
}
}
};
return new DefaultNodeInfo<Employee>(dataProvider, cell,selectionModel, null);
}
return null;
}
#Override
public boolean isLeaf(Object o) {
if (o instanceof Employee) {
return true;
}else if(o instanceof Person){
return true;
}
else return false;
}
}
in my actual code I can't mix Employees data and Person's Data because two different objects
Any way to do that ?
A listDataProvider who brings two Objects maybe ?

Constructor of a child class

folks.... i have a child class GateNot which extends Gate. I'm not sure how to fill out the constructor of GateNot since Im not given any instance variables inside a child class. What would be the approach?
public class GateNot extends Gate {
public GateNot(Wire input, Wire output)
{
super()
}
}
import java.util.*;
public abstract class Gate implements Logic {
private List<Wire> inputs;
private Wire output;
private String name;
public Gate(String name, List<Wire> ins, Wire out)
{
this.name = name;
this.output = out;
if(ins.size() == 0 || ins.isEmpty())
throw new ExceptionLogicParameters(false, 1, 0);
else
this.inputs = ins;
}
#Override
public void feed(List<Signal> inSigs)
{
if(inSigs.size() != inputs.size())
throw new ExceptionLogicParameters(false, inputs.size(), inSigs.size());
else
{
for(int i = 0; i < inSigs.size(); i++)
{
inputs.get(i).setSignal(inSigs.get(i));
}
}
}
#Override
public void feed(String name)
{
if(!(this.name.equals(name)))
throw new ExceptionLogicMalformedSignal(name.charAt(0), "Invalid logic input");
else
{
Signal signalValue = Signal.fromString(name.charAt(0));
}
}
#Override
public List<Signal> read()
{
List<Signal> signals = new ArrayList<>();
signals.add(output.getSignal());
return signals;
}
#Override
public String toString()
{
return this.name+"( " + inputs.toString() + " | " + output.toString() + " )";
}
#Override
public boolean equals(Object other)
{
if(other instanceof Gate)
{
Gate someGate = (Gate)other;
return (this.inputs == someGate.inputs) && (this.output.equals(someGate.output)
&& (this.name.equals(someGate.name)));
}
else
return false;
}
public List<Wire>getInputs()
{
return this.inputs;
}
public Wire getOutput()
{
return this.output;
}
public String getName()
{
return this.name;
}
public void setInputs(List<Wire> inputs)
{
this.inputs = inputs;
}
public void setOutput(Wire output)
{
this.output = output;
}
public void setName(String name)
{
this.name = name;
}
}
You have to call the super class's constructor.
Based on the argument types and names of the super class's constructor, I'd say this is what you need :
public GateNot(Wire input, Wire output)
{
super("Not", Arrays.asList(new Wire[]{input}), output);
}
You can pass whatever String you wish as name
You should convert the input to a List of inputs
You can pass the output as is

Categories