creating map of values from object - java

we have
class Student
{
String name,
int age,
String specialization
}
and
class Students
{
List<String> names,
List<Integer> age,
List<String> specialization
}
Students object is basically a structure that holds field values of Student class,
What is the best way to fill Students object without using reflection.
Edit: we have a specific requirement of having Students class as it is, the reason for this is we don't always want all the information in Student class and if we have List it would allocate memory for the fields that we are not interested in.

Don't create class Students. Hold a list of Student
List<Student> students = new ArrayList<Student>();
And to access a student data you can use
students.get(0).name;
As a side note, you should learn about getters and setters.

I wouldn't recommend creating a class named "Students" for this purpose. Your intention is to create a collection to hold the Student objects.
In this case, do the following:
List<Student> students = new ArrayList();
Also, pay attention to the capitalization: class is a keyword and should be spelled all lower-case.
EDIT After seeing a comment from venkat:
If you really need to create a class called Students then following should work (also similar answer provided above by another SO user):
class Students {
List<Student> students = new ArrayList();
}
This should work, but I would highly recommend not to use these type of class with the plural names!
PS: I am a CS prof teaching programming languages in a university and a long time developer/consultant.

Class Students {
List<Student> students;
}

Maybe you want to use a Decorator-Pattern (I don't think that i saves memory):
Implement a base class with the default field:
public class BaseClass implements INameGettable {
protected String name;
public BaseClass(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Add the default interface:
public interface INameGettable {
String getName();
}
Add a decorator to for an additional field e.g. age:
public class Decorator implements INameGettable {
protected INameGettable nameable;
protected int age;
public Decorator(INameGettable nameable, int age) {
this.nameable = nameable;
this.age = age;
}
public String getName() {
return nameable.getName();
}
public int getAge() {
return this.age;
}
}
Usage:
// First object contains only name
INameable namegettable = new BaseClass("Test1");
namegettable.getName();
// Second object contains name and age
Decorator agegettable = new Decorator(new BaseClass("Test2"), 77);
agegettable.getName();
agegettable.getAge();

Going for the obvious answer here.
class Students
{
List<String> names;
List<Integer> age;
List<String> specialization;
public Student(List<Student> students) {
addStudents(students);
}
private void addStudents(List<Student> students) {
names = students.stream
.map(Student::getName)
.collect(Collectors.toList())
age = students.stream
.map(Student::getAge)
.collect(Collectors.toList())
specialization = students.stream
.map(Student::getSpecialization)
.collect(Collectors.toList())
}
}

Related

How to check if a string already exist in ArrayList?

I made this Student ArrayList that have name, age and number variable. I manually input 3 student. I want to check if a name already exist in my list. I tried to use list.contains but it seems not working. Are there certain way to do for this kind of ArrayList?
public class CompareToeX {
public static void main(String[] args) {
ArrayList<Student> obj=new ArrayList<Student>();
obj.add(new Student("Peter", 27,1));
obj.add(new Student("John",26,7));
obj.add(new Student("Jack",21,5));
if(obj.contains("Peter")){
System.out.println("Peter on is on the list!");
} else {
System.out.println("Peter is not on the list!");
}
}
}
This is the Student class
public class Student{
private String studentName;
private int age;
private int rollno;
public Student(String studentName, int age, int rollno){
this.studentName=studentName;
this.age=age;
this.rollno=rollno;
}
public String getStudent(){
return studentName;
}
public int getAge(){
return age;
}
public int getRollno(){
return rollno;
}
public void setStudent(String Student){
studentName=Student;
}
public void setAge(int age){
this.age=age;
}
public void setRollno(int rollno){
this.rollno=rollno;
}
}
After I run, the result should show that peter is on the list right. But it goes the other way around. It seems that the contains method is not working.
A student isn't a name.
.contains() will fail here because the string "Peter" is not in the list. It obviously isn't; how could it be? This list only contains Student objects, not Strings, after all.
You'll have to write a for loop, or use streams.
boolean peterIsInTheList = false;
for (var s : students) {
if (s.getName().equals("peter")) peterIsInTheList = true;
}
or
boolean peterIsInTheList = students.stream()
.anyMatch(s -> s.getName().equals("peter"));
Alternatively you could use the idea of a map; change your data structure. Instead of using a list, have a map that maps first names onto student objects:
Map<String, Student> students = new HashMap<>();
students.put("peter", new Student(....));
if (students.containsKey("peter")) {
// peter is in the list
}
You are checking if the String Peter is in the list, or the list only contains Student object. So you can only check if Student is contained inside the list (be sure to implement the right equals/hashcode method if you wish to use .contains).
This will do
obj.stream()
.filter(student -> student.getStudent().contains("Peter"))
.findFirst()
.ifPresentOrElse(student -> System.out.println("Peter on is on the list!"), () -> System.out.println("Peter is not on the list!"));
Being not a default data type, I think you need to override some functions of ArrayList first, like the .compare() one.
It was answered here too
Java: to use contains in a ArrayList full of custom object should I override equals or implement Comparable/Comparator?

Generate different object with same attributes

I am building a project. One of the requirements is to generate the object with the same attributes but randomly different values. I tried to use deep-copy, but not sure if it is conceptually correct.
So, for example, I have a Person class, inherited from the abstract class Character.
And there is a ScenarioGenerator, which I'll put the getRandomPerson method to create the instances of the Person class.
Any help of advice is highly appreciated.
Here is part of my Person class:
public class Person extends Character {
private Random random;
private boolean pregnant;
private boolean isYou;
Person(int age, Profession profession ,Gender gender, BodyType bodyType, boolean isPregnant) {
super(age, gender, bodyType);//pass the attributes to the super class called Character
}
Person (Person otherPerson) { //copy constructor
this.age = otherPerson.getAge();
this.gender = otherPerson.getGender();
this.bodyType = otherPerson.getBodyType();
}
public Profession getProfession () { // One of the getters which generate random enum value
//only adults have profession
if (getAge()<=16 || getAge()>68) {
return Profession.NONE;
} else {
return Profession.values()[new Random().nextInt(Profession.values().length)];
}
}
// setters and getters
}
And the method of my ScernarioGenerator class:
public class ScenarioGenerator {
public Person getRandomPerson() {
//need age, gender, bodyType, profession, pregnancy
Person people = new Person(person.getAge(), person.getProfession(), person.getGender(), person.getBodyType(), person.isPregnant());
Person clone = new Person(people);
return clone;
}
If you want a deeply cloned object then you can get it by implementing the clone class and overriding the clone function like
public class Person extends Character implements Cloneable {......}
Then you may simply get the new deep copied object by
Person clone=(Person) people.clone();

Passing an object array to method

So I want to use a method to write multiple objects to respective files. However I do not know how to import the array of Objects without defining the specific Object.
The people is class is purely for storing the created objects in arrays so it is easier to access across other classes.
For example
public class People {
private Student[10];
private Teacher[10];
public void setStudentArray(Student, index) {
Student[index] = Student;
}
public void setTeacherArray(Teacher, index) {
Teacher[index] = Teacher;
}
}
public class Student extends People {
String name;
int StudentID;
public String getName() {
return name;
}
}
public class Teacher extends People {
String name ;
int Teacher ID;
public String getName() {
return name;
}
}
public class Main {
People p = new People();
public void main (String[] args) {
Student s = new Student("default-name" , 1);
p.setStudentArray(s, 0);
Teacher t = new Teacher("default-name", 1);
p.setTeacherArray(t, 0);
outputName(p.getStudentArray, 0);
outputName(p.getTeacherArray, 0)
}
//THIS IS WHERE I AM STRUGGLING I dont know how to pass teachers or students array to it.
//I want the Object[] parameter to accept both Student[] and Teacher[]
public void outputName(Object[], index) {
System.out.println(Object[index].getName);
}
}
I think that my Method taking an Object[] is wrong but I do not know how to approach it otherwise. I believe the issue is that Object[] is an entirely different class to Teacher[] and Student[] and this is where I am going wrong.
I want to use the .getName method in both the classes of Teacher and Student in order to print the name of the Teacher of Student. (Merely so I can see the passing is working.)
If this is just not possible I guess I will just not try a method that can take different objects.
I know that I can just use two methods one for students and one for teachers but I want the method to work for multiple objects so that I can add more object arrays to it.
So People class is extended by both Student and Teacher.
What commonalities are here?
String name is present in both Student and Teacher
public String getName() is also present in both Student and Teacher
You can move these commonalities to People class. Also ensure to remove the name attribute and getName from Student and Teacher class
So your People updated class can be:
public class People {
private String name; //Newly added
private Student[10]; //This ideally shouldn't be in People class rather a different class
private Teacher[10]; //This ideally shouldn't be in People class rather a different class
public void setStudentArray(Student, index) {
Student[index] = Student;
}
public void setTeacherArray(Teacher, index) {
Teacher[index] = Teacher;
}
public String getName() {
return name;
}
public void setName() {
this.name = name;
}
}
The outputname method should be like:
public void outputName(People[] people, index) {
System.out.println(people[index].getName());
}
NOTE: I am not correcting the syntax here, but just giving an idea.
What #Li357 said is right... You have to change your modeling a bit. Even if you managed to pass Student[] as an Object[], you wouldn’t be able to call the getName method as it’s not an Object method.
So a better modeling would be to make the getName method a People method, and both Student and Teacher classes would inherit it.
Then you could receive People[] as the outputName method argument, and use the getName method inside.
First of all learn how to declare array and choose valid variables.
In your People class do following modifications.
public class People {
//Declare arrays like this.
private Student[] student;
private Teacher[] teacher;
//Initialize arrays
public People(){
student = new Student[10];
teacher = new Teacher[10];
}
public void setStudentArray(Student s,int index) {
student[index] = s;
}
public void setTeacherArray(Teacher t, int index) {
teacher[index] = t;
}
//Add getter methods
public Student[] getStudentArray(){
return student;
}
public Teacher[] getTeacherArray(){
return teacher;
}
}
Inside sub classes Student and Teacher add Argument constructor
Finally in your outputName method you can do something like this.
public static void outputName(Object[] obj, int index) {
if(obj instanceof Student[]){
Student[] s = (Student[])obj;//parsing to student array
System.out.println("Student name : "+s[index].getName());
}
if(obj instanceof Teacher[]){
Teacher[] teacher = (Teacher[])obj;//parsing to teacher array
System.out.println("Teacher name : "+teacher[index].getName());
}
}
Output:
Student name : default-name
Teacher name : default-name

Is there a way to get an arraylist element by its name? [duplicate]

This question already has answers here:
How to find an object in an ArrayList by property
(8 answers)
Closed 6 years ago.
I write a program in Java, and i have the following problem:
//this is the important part of my class student
public class Student{
private String name;
public Student(String name){
this.name = name;
}
//Getter
public String getName() {
return name;
}
}
//this is the other class (could be the main for example)
public class Load {
private ArrayList<Student> student= new ArrayList<Student>();
student.add(new Student(name));
}
Later in the program I need those students again. I can get them like this:
System.out.println(student.get(0));
But I dont have the number of the students. Is there a way to get them by the name, which is in the class Student?
What you can do is create a function which takes a String as input, searches the student list and returns if the object was found.
public Student findStudentByName(String name) {
for(Student studentObj : student) {
if(studentObj.getName().equals(name)) {
return studentObj;
}
}
return null;
}
In this case maybe you can use a Map to save that list of Students. Then you shoud get Students by name.
Map<String, Student> students = new HashMap<String, Student>();
Student maryIn = new Student();
maryIn.setName("Mary");
students.put(maryIn.getName(), maryIn);
Student maryOut = students.get("Mary");
You can get the number of elements in a list by using student.size().
Additionally, you should use interface type whenever possible, in your case List<Student> student = new ArrayList<Student>();.
Also, have a typo in your code: student.add(new Student(name));.
As for the last question, just use an extra method inside Load that searches for the desired student name in the current list:
public Student searchByName(String targetStudentName) {
for (Student s : student) {
if (targetStudentName.equals(s.getName())) {
return s;
}
}
return null;
}

how to use array list to access methods of access list type object in java

in my program there are three class Student,School and TestStudent. I have declared students state inside student class and also there are methods for getting students subject,i have created an array list of type student in School class,but when i try to access student's method in school i get error newStudent type can not be resolved.Here are my codes.
public class Student {
String name;
String subject;
int age;
Student(String name,String subject,int age){
this.name = name;
this.subject = subject;
this.age = age;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
public String getSubject(){
return this.subject;
}
public int getAge(){
return this.age;
}
}
public class School {
public ArrayList <Student> students = new ArrayList <Student>();
public void addStudent(String name,String subject,int age){
Student newStudent = new Student(name,subject,age);
students.add(newStudent);
}
public void showSubject(String student){
newStudent.getSubject();
}
}
newStudent.getSubject();
This is not what you want. Because you haven't retrieved that student yet from the ArrayList.
You would need to iterate over the ArrayList, and see which student have the name as passed in parameter.
So, just use a for-each loop to iterate over your ArrayList, and return appropriate Student.
So, your method should look like: -
public void showSubject(String student){
for (Student student: students) {
if (student.getName().equals(student)) {
System.out.println(student.getSubject());
}
}
}
Note that, using a Map here would be a better idea as explained by #Peter in his answer.
If you want to look up a student by name, I would make the name of a student immutable and use a Map<String, Student> instead. This would allow you to write
Student student = map.get(studentName);
Using a List, you would have to search through every entry as Rohit suggests. Note: it is possible to have multiple students with the same name (as in real life) with a List.
newStudent is a local variable in addStudent(), hence you cannot access it from showSubject().
I don't know what should be your logic of accessing the subject, but, for example, it could be accessed via students.get(0).getSubject() [provided the list is not empty]

Categories

Resources