Java different objects in a single method - java

I Know there are a bunch of questions related with this topic. Most of the answers states "use a interface" or "create a generic". Tried both and didnt work =( dont know what I'm doing wrong.
Here is the problem: I have two classes: Subjects and Courses. In the main section, I want a function that will receive an id (provided by the user) and look into, for example, a subjectList, trying to find if the subject is there, if yes , return its index. The logic is the same for both Courses and Subjects, so I'm trying to let this function become a bit more generic.
public static void main(String[] args) {
//Objects created along the code are stored here
ArrayList<Course> courseList = new ArrayList<>();
ArrayList<Subject> subjectList = new ArrayList<>();
public static Integer findObjectById(int id, ArrayList<IStudyDetails> object_list) {
for (int i = 0; i < object_list.size(); i++) {
if (id == object_list.get(i).getId()) {
return i;
}
}
return null;
}
int index_subject = findObjectById(subject_id,subjectList);
}
Here is the Interface:
I tried to create this after look into some Stack Overflow related topics.
public interface IStudyDetails{
int getId();
}
Here is the Course class: (I did hide most of the constructors/gets and setters)
public class Course implements IStudyDetails {
private int id;
private String name;
public int getId() {return id;}}
Here is the Subject class (I did hide most of the constructors/gets and setters)
public class Subject implements IStudyDetails {
private int id;
private String name;
public int getId() {return id;}}
THe error I'm receiving is:
java: incompatible types: java.util.ArrayList<entities.Subject> cannot
be converted to java.util.ArrayList<entities.IStudyDetails>

public static void main(String[] args) {
//Objects created along the code are stored here
List<IStudyDetails> courseList = new ArrayList<>();
List<IStudyDetails> subjectList = new ArrayList<>();
Subject subject = new Subject(0001, "John");
Subject subject1 = new Subject(1001, "Tom");
subjectList.add(subject);
subjectList.add(subject1);
int subject_id = 1001;
int index_subject = findObjectById(subject_id,subjectList);
}
public static Integer findObjectById(int id, List<IStudyDetails> object_list) {
for (int i = 0; i < object_list.size(); i++) {
if (id == object_list.get(i).getId()) {
System.out.println(i);
return i;
}
}
return null;
}
I Just change the List Type, Cause both Course and Subject are implemented from IStudyDetails, so you need to use IStudyDetails as a type to create the list and it can work.

Related

Find highest age of person in Array and return name

Task: your task is to expand the class PersonRegister through coding the method nameOftheOldest(). The methods task is to find and return the name of the person that is the oldest in the register (that is the oldest of those stored in the list allPersons array).
Code of the class looks like this:
public class PersonRegister
{
// instance variables - replace the example below with your own
private Person[] allPersons;
/**
* Constructor for objects of class PersonRegister
*/
public PersonRegister(int numberOfPersons)
{
// initialise instance variables
this.allPersons = new Person[numberOfPersons];
}
public void registreraPerson(int index, Person aPerson)
{
allPersons[index] = aPerson;
}
}
There is another class called Person in the program that looks like this:
public class Person
{
// instance variables - replace the example below with your own
private String name;
private int birthYear;
/**
* Constructor for objects of class ExperimentJavaLoops
*/
public Person(String name, int birthYear)
{
// initialise instance variables
this.name = name;
this.birthYear = birthYear;
}
public String getName()
{
return name;
}
public int birthYear()
{
return birthYear;
}
public void setName(String name)
{
this.name = name;
}
public void setbirthYear(int birthYear)
{
this.birthYear = birthYear;
}
}
Googled this a lot, read literature and tried to code it but cant find a solution. I think I'm supposed to loop through the array and compare values inside the loop through an if-statement. Then also use external method calls to get the name and birthyear (oldest will be the person with lowest birthyear, naturally). And it should be converted to String and returned in order to return name? Confused. Very new to programming and a bit more used to ArrayLists than Arrays.
Or you could use a stream approach:
Optional<Person> eldest = Arrays.stream(allPersons)
.collect(Collectors.maxBy((p1, p2) -> Integer.compare(p1.getAge(), p2.getAge())));
System.out.println("Eldest is " + eldest.get());
But you might want to do a simple iteration, keeping track of the current oldest, as has been suggested
This should get you started.
public String nameOfTheOldest()
{
Person oldest = allPersons[0];
for (int i = 1; i < allPersons.length; i++)
{
if (allPersons[i] ...)
...
}
return ...;
}
I tried this. Returns the
age as a string but not the name. Also i get "Exception occurred" if the amount
of Person objects in the array do not match the length of the array when i use the method.
Code:
public String nameOfTheOldest() {
// oldest == earliest birthYear.
String str= "";
Person oldest = allPersons[0];
int oldestINT = oldest.birthYear();
for (int i = 1; i < allPersons.length; i++)
{
Person maybeOldest = allPersons[i];
int perhapsOldest = maybeOldest.birthYear();
if (perhapsOldest < oldestINT)
oldestINT = perhapsOldest;
str = String.valueOf(oldestINT);
}
return str;
}
Use below code -
public String nameOfTheOldest() {
Person oldest = allPersons[0];
for (int i = 1; i < allPersons.length; i++)
{
Person p = allPersons[i];
if (p.birthYear() < oldest.birthYear()) {
oldest = p;
}
}
return oldest.name();
}

How to migrate Room database with ArrayList field?

There is an already created #Embedded class Player. I want to add to it the ArrayList field, which uses #TypeConverters, which converts my List to Gson when saving and back when loading.
Please tell me how to make a request in the void migrate ()
method to add the list to an already existing instance of the Player
class.
#Database(entities = {Save.class}, version = 2)
public abstract class AppDatabase extends RoomDatabase {
public static final Migration MIGRATION_1_2 = new Migration(1, 2) {
#Override
public void migrate(final SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE Save ADD COLUMN trainingPower
INTEGER DEFAULT 5 NOT NULL");
}
};
}
Player class:
public class Player
{
#TypeConverters({AlbumsListConverter.class})
private List<Albums> albumsList = new ArrayList();
#Embedded(prefix="energy_")
public Skills energy;
public int energyCount;
public int energyMax = 50;
public String fameName;
#Embedded(prefix="flow_")
public Skills flow;
public int imageID;
int imagePers;
#Embedded(prefix="mast_")
public Skills mastering;
#Embedded(prefix="mast2_")
public Skills mastering2;
private long money = 50;
#Embedded(prefix="music_")
public Skills music;
private String name;
public int ratingPosition = 1;
public int reclameToken = 0;
#TypeConverters({TrackListConverter.class})
public List<Tracks> releaseList = new ArrayList();
#TypeConverters({MessagesConverter.class})
public List<Massages> messagesList = new ArrayList<>();
private long reputation = 0;
private int respect = 1;
...
}
class Save:
#Entity
public class Save
{
#TypeConverters({ArrayConverter.class})
public String[] AllTopicTracks;
#Embedded
private Player actor;
...
}
TypeConverter:
public class MessagesConverter {
#TypeConverter
public String fromMassagesList(List<Messages> messages)
{
Gson gson = new Gson();
return gson.toJson(messages);
}
#TypeConverter
public List<Messages>toMessagesList(String data)
{
Gson gson = new Gson();
Type type = new TypeToken<List<Messages>>(){}.getType();
return gson.fromJson(data,type);
}
}
It seems you had used #Embedded for multiple variables. If #Embedded is annotated the variables of model class is treated as column for the same table. So for the case of multiple objects of same type you shoud use TypeConverter where the object can be converted to json string while saving and later retrieved as the object.
Instead of making embedded Player, create type converter for player and use it. By doing this you don't have to create separate type converter for objects inside player.

What Pattern design to get rid of the type casting in my case?

public abstract class Employee {
String name;
String position
public Employee(String name, String position) {
this.name = name;
this.position = position
}
}
public class Pilot extends Employee {
public Pilot(String name,String position) {
super();
}
public void flight() {//flight the plane}
//getter and setter for the fields
}
public class Attendance extends Employee {
public Attendance(String name,String position) {
super();
}
public Food servingFood(String foodName) {}
}
// there will be many other positions
public class Company {
HashMap<String, ArrayList<Employee>> employeeTable; //values is a list of workers, key is the position
public Company() {this.employeeTable = new HashMap<>();}
public initializeEmployeeTable(file) {} //read file, and create keys in map (file contains information of the position)
public Worker hireEmployee(String position, String name){
if (position.equals("pilot")) {
Pilot p = Pilot(name);
employeeTable.get("pilot").add(p);
return p
}
else if (position.equals("flightAttendance")) {// the else if statement continuous to check the other position; }
}
public Worker callEmployee(String position, String name) {
for ( Employee e : employeeTable.get(position) ) {
if e.getName().equals(name) {
return e;
}
}
return null;
}
public static void main(String[] args) {
Company company = new Company();
company.initializeEmployeeTable(filePath);
File eventFile = new File(filePath); // event file describes what's happening in real world; read the lines, and call the program so that program simulates the real world events
sc = new Scanner(eventFile);
do {
String currentEvent = sc.nextLine();
String[] currentEventParts = currentEvent.split(", ");
if (currentEvent[0].equals("New Airplane")) { // currentEvent looks like {"New Airplane", "Attendance"// this part can be other position name, "Linda"}
Worker w = company.hireEmployee(currentEventParts[1], currentEventParts[2]); }
else if ((currentEvent[0].equals("flying"))) {
Worker w = company.callEmployee(currentEvent[0], currentEvent[1])
if (w.getPosition().equals("Pilot")) {(Worker) w.flight()}
if (w.getPosition().equals("Attendance")) {(Worker) w.serveFood()}
}
}
The reason there is HashMap for employee because there will be many positions; and reading the event file (when the first index is "New Airplane"); I don't want to go check the following index (would be name and position) with so many if statements to create corresponding employee. But when comes to calling specific methods, I need type casting now; since each method can be different (different type parameter, return type); so it's not ideal to have this methods be abstract method in super class employee and have the subclass implements the body.
Any advices: employee data structure; reading file strategy, pattern design would be appreciated. thanks

How to forbid creation of two class objects with the same parameters?

friends and colleagues. I have following class:
public class Department {
private String departmentName;
private int moneyForDepartment;
public Department(String departmentName, int moneyForDepartment){
if (moneyForDepartment < 0){
throw new IllegalArgumentException("invalid value");
}
this.departmentName = departmentName;
this.moneyForDepartment = moneyForDepartment;
}
public Department(){
}
public String getDepartmentName() {
return departmentName;
}
public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}
public int getMoneyForDepartment() {
return moneyForDepartment;
}
public void setMoneyForDepartment(int moneyForDepartment) {
this.moneyForDepartment = moneyForDepartment;
}
}
and for example i will create two objects of this class:
Department dep1 = new Department("Storage", 100000);
Department dep2 = new Department("Storage", 200000);
Please tell me how can i forbid to create class object in case when object of this class with the same first parameter is already exists ?
It's probably not a good idea to do that globally across your entire application (in static state), because then testing becomes difficult. Instead, create a factory for your Department class, maybe looking something like this:
public class Department {
private Department(String departmentName, int moneyForDepartment) { ... }
...
public static class Factory {
private Set<String> seenDepartmentNames = new HashSet<>();
public Department create(String departmentName, int moneyForDepartment) {
if (!seenDepartmentNames.add(departmentName)) {
throw new IllegalArgumentException("Department already created");
}
return new Department(departmentName, moneyForDepartment);
}
}
}
This forces all construction to go through the Factory, since the Department constructor is private. Just use one Factory across your application, and you can still create new ones for testing without running into problems.
You could create a static field in the Department class and keep a Set with the department names already used:
public class Department {
private static final Set<String> usedDepartmentNames = new HashSet<>();
...
}
Then, in the constructor, do:
public Department(String departmentName, int moneyForDepartment) {
if (usedDepartmentNames.contains(departmentName)) {
throw new IllegalArgumentException("Department already exists");
}
if (moneyForDepartment < 0){
throw new IllegalArgumentException("invalid value");
}
this.departmentName = departmentName;
this.moneyForDepartment = moneyForDepartment;
usedDepartmentNames.add(departmentName);
}

Implementing the Comparator interface [duplicate]

This question already has answers here:
Implementing Java Comparator
(2 answers)
Closed 7 years ago.
I want to make a comparator class that implements the comparator interface. In the class I want to compare 2 of my employee objects based on their ID. The employee class that I have made so far is:
import java.util.ArrayList;
public class Employee {
public int ID_Number;
public String Full_Name;
public double Salary;
static ArrayList<Object> employ = new ArrayList<Object>();
Employee(int id, String name, double sal){
ID_Number = id;
Full_Name = name;
Salary = sal;
}
}
I'm totally stuck on this and don't have any idea what to do. Can anybody help?
Here's a Comparator inner class from my little project DBvolution:
private static class ClassNameComparator implements Comparator<Class<?>>, Serializable {
private static final long serialVersionUID = 1L;
ClassNameComparator() {
}
#Override
public int compare(Class<?> first, Class<?> second) {
String firstCanonicalName = first.getCanonicalName();
String secondCanonicalName = second.getCanonicalName();
if (firstCanonicalName != null && secondCanonicalName != null) {
return firstCanonicalName.compareTo(secondCanonicalName);
} else {
return first.getSimpleName().compareTo(second.getSimpleName());
}
}
}
That might look complicated but it's actually simple. The basic principle is below:
class ClassNameComparator implements Comparator<YourClass> {
ClassNameComparator() {
}
#Override
public int compare(YourClass first, YourClass second) {
if (first > second){
return 1;
} else if (first == second){
return 0;
} else return -1;
}
}
You'll need to replace YourClass with your class and change the tests to something more appropriate for your objects. Finally remember to check for nulls.

Categories