I have a number of Customer objects stored in an ArrayList. My Customer class has 2 data members: Name and Email. Now I want to modify just the Email for Customer "Doe".
Now if "Doe" is located at index 3 in the list, I know I can write this line:
myList.set( 3, new Customer( "Doe", "j.doe#supermail.com" ) );
But that means creating a new object. If I have a very big list, I suppose the process would be very slow. Is there any other way to directly access the data member of an Object stored in an ArrayList, maybe by using another kind of Collection than ArrayList?
You can do this:
myList.get(3).setEmail("new email");
Fixed. I was wrong: this only applies on element reassignment. I thought that the returned object wasn't referencing the new one.
It can be done.
Q: Why?
A: The get() method returns an object referencing the original one.
So, if you write myArrayList.get(15).itsVariable = 7or myArrayList.get(15).myMethod("My Value"),you are actually assigning a value / using a method from the object referenced by the returned one (this means, the change is applied to the original object)
The only thing you can't do is myArrayList.get(15) = myNewElement. To do this you have to use list.set() method.
You can iterate through arraylist to identify the index and eventually the object which you need to modify. You can use for-each for the same as below:
for(Customer customer : myList) {
if(customer!=null && "Doe".equals(customer.getName())) {
customer.setEmail("abc#xyz.com");
break;
}
}
Here customer is a reference to the object present in Arraylist, If you change any property of this customer reference, these changes will reflect in your object stored in Arraylist.
Assuming Customer has a setter for email - myList.get(3).setEmail("j.doe#supermail.com")
I wrote you 2 classes to show you how it's done; Main and Customer. If you run the Main class you see what's going on:
import java.util.*;
public class Customer {
private String name;
private String email;
public Customer(String name, String email) {
this.name = name;
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#Override
public String toString() {
return name + " | " + email;
}
public static String toString(Collection<Customer> customers) {
String s = "";
for(Customer customer : customers) {
s += customer + "\n";
}
return s;
}
}
import java.util.*;
public class Main {
public static void main(String[] args) {
List<Customer> customers = new ArrayList<>();
customers.add(new Customer("Bert", "bert#gmail.com"));
customers.add(new Customer("Ernie", "ernie#gmail.com"));
System.out.println("customers before email change - start");
System.out.println(Customer.toString(customers));
System.out.println("end");
customers.get(1).setEmail("new.email#gmail.com");
System.out.println("customers after email change - start");
System.out.println(Customer.toString(customers));
System.out.println("end");
}
}
to get this running, make 2 classes, Main and Customer and copy paste the contents from both classes to the correct class; then run the Main class.
Use myList.get(3) to get access to the current object and modify it, assuming instances of Customer have a way to be modified.
You can just do a get on the collection then just modify the attributes of the customer you just did a 'get' on. There is no need to modify the collection nor is there a need to create a new customer:
int currentCustomer = 3;
// get the customer at 3
Customer c = list.get(currentCustomer);
// change his email
c.setEmail("somethingelse#example.com");
Well u have used Pojo Entity so u can do this.
u need to get object of that and have to set data.
myList.get(3).setEmail("email");
that way u can do that. or u can set other param too.
If you need fast lookup (basically constant time) of a object stored in your collection you should use Map instead of List.
If you need fast iteration of the objects you should use List.
So in your case...
Map<String,Customer> customers = new HashMap<String,Customer>();
//somewhere in the code you fill up the Map, assuming customer names are unique
customers.put(customer.getName(), customer)
// at some later point you retrieve it like this;
// this is fast, given a good hash
// been calculated for the "keys" in your map, in this case the keys are unique
// String objects so the default hash algorithm should be fine
Customer theCustomerYouLookFor = customers.get("Doe");
// modify it
theCustomerYouLookFor.setEmail("newEmail#stackoverflow.com")
Without function here it is...it works fine with listArrays filled with Objects
example
`
al.add(new Student(101,"Jack",23,'C'));//adding Student class object
al.add(new Student(102,"Evan",21,'A'));
al.add(new Student(103,"Berton",25,'B'));
al.add(0, new Student(104,"Brian",20,'D'));
al.add(0, new Student(105,"Lance",24,'D'));
for(int i = 101; i< 101+al.size(); i++) {
al.get(i-101).rollno = i;//rollno is 101, 102 , 103, ....
}
Any method you use, there will always be a loop like in removeAll() and set().
So, I solved my problem like this:
for (int i = 0; i < myList.size(); i++) {
if (myList.get(i).getName().equals(varName)) {
myList.get(i).setEmail(varEmail);
break;
}
}
Where varName = "Doe" and varEmail = "j.doe#supermail.com".
I hope this help you.
Try this.This works while traversing the code and modifying the fields at once of all the elements of Arraylist.
public Employee(String name,String email){
this.name=name;
this.email=email;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setEmail(String email) {
this.email = email;
}
public String getEmail() {
return email;
}
for(int i=0;i++){
List.get(i).setName("Anonymous");
List.get(i).setEmail("xyz#abc.com");
}
Related
public static void getIndividualsList() {
List<Employee> individualList = new ArrayList<>();
Employee individualDtls = new Employee();
individualDtls.setDependentId(0);
individualDtls.setDateOfBirth("06/06/1998");
individualDtls.setEeId(1L);
individualDtls.setFullName("MICHAEL K HERNANDEZ");
individualDtls.setCovered(false);
individualDtls.setDependentType("Self");
individualList.add(individualDtls);
List<Employee> individualList1 = new ArrayList<>();
Employee individualDtls1 = new Employee();
individualDtls1.setDependentId(0);
individualDtls1.setDateOfBirth("06/06/1998");
individualDtls1.setEeId(1L);
individualDtls1.setFullName("MICHAEL K HERNANDEZ");
individualDtls1.setCovered(false);
individualDtls1.setDependentType("Self");
individualList1.add(individualDtls1);
individualList.removeAll(individualList1);
for (Employee employee : individualList) {
System.out.println(employee.getDateOfBirth());
}
}
Why removeAll is not working properly?
Applied removeAll but still getting data. Can someone please let me know why its not working?
Based on your comment: "In the employee class there is restriction. So its not allowing to modify like adding any other methods or comparator. Thats the problem. Thats why trying to find another solution for that."
If you have any unique field, maybe you can use that field to iterate over your first list to remove the required items.
import java.util.*;
public class MyClass {
public static void main(String args[]) {
List<Employee> listA = new ArrayList<>();
listA.add(new Employee("gokul", "1", "gokul#domain.com"));
listA.add(new Employee("user", "2", "user#domain.com"));
List<Employee> listB = new ArrayList<>();
listB.add(new Employee("user", "2", "user#domain.com"));
for (Employee eB : listB) {
for (Employee eA : listA) {
if (eA.id.equals(eB.id)) {
listA.remove(eA);
break;
}
}
}
for (Employee e : listA) {
System.out.println(e.name);
}
}
static class Employee {
String name;
String id;
String email;
public Employee(String name, String id, String email) {
this.name = name;
this.id = id;
this.email = email;
}
}
}
Both remove and removeAll relies on equal (and hashCode!) implementation. Most probably you didn't implement one of this methods.
Without custom implementation of equal an object equals only himself. Two variables must reference exactly the same object to be equal. Custom implementation looks like this:
class Employee {
....
public boolean equals(Object obj) {
if (obj instanceof Employee) {
Employee oo = (Employee)obj;
return Objects.equal(fullName, oo.fullName) && Objects.equal(dateOfBirth, oo.dateOfBirth)
} else {
return false;
}
}
public int hashCode() {
return Objects.hashCode(fullName, dateOfBirth);
}
}
I took fullName and dateOfBirth to ensure equality. You must manually add all the fields you think important for two objects to be equal (spoiler - it is not trivial).
If you cannot modify the object Employee there are to ways:
do it manually as described by "Gokul Nath KP"
take some other collection structure instead of ArrayList. For example TreeSet uses an optionally provided custom Comparator instance instead of equal-Method.
I came across this exercise online where I have two classes and I'm supposed to make the Tutor class immutable. However, the only thing I can think of is adding final to name field. When it comes to the constructor, I don't think I need to change the initialisation of the name variable as String is immutable. I'm not sure how to approach the collection and how to make this part of the constructor immutable. According to the exercise, I'm not supposed to change the Student class (which I can see is mutable)
public class Student {
private String name;
private String course;
public Student(String name, String course) {
this.name = name;
this.course = course;
}
public String getName() {
return name;
}
public String getCourse() {
return course;
}
public void setName(String name) {
this.name = name;
}
public void setCourse(String course) {
this.course = course;
}
}
public final class Tutor {
private String name;
private final Set<Student> tutees;
public Tutor(String name, Student[] students) {
this.name = name;
tutees = new HashSet<Student>();
for (int i = 0; i < students.length; i++)
tutees.add(students[i]);
}
public Set<Student> getTutees() {
return Collections.unmodifiableSet(tutees);
}
public String getName() {
return name;
}
}
The Tutor class presents many aspects promoting its immutability :
the class is final
the Set<Student> is protected against the modifications
no method allowing to change directly the state of the class
However, the defensive copy of the constructor is not complete.
It also has to copy the Students elements of the array passed. Otherwise the client of the constructor may change any instance of them and make so the Tutor instance mutable such as :
Student[] students = ...;
Tutor tutor = new Tutor(name, students);
students[0].setName("new Name!"); // break the immutability of Tutor
You should write something like :
public Tutor(String name, Student[] students){
this.name = name;
tutees = new HashSet<Student>();
for (Student student : students){
Student copy = new Student(student.getName(),
student.getCourse());
tutees.add(copy);
}
}
Additionally note that the Set returned by getTutees() is unmodifiable but elements contained in are as Student is mutable.
So to make Tutor immutable you also have to create a copy of the Student elements as you return getTutees() such as :
public Set<Student> getTutees(){
Set<Student> students = new HashSet<>();
for (Student student : tutees){
Student copy = new Student(student.getName(),
student.getCourse());
students.add(copy);
}
return Collections.unmodifiableSet(students);
}
As you may notice, getting the immutability in these conditions (an instance that we wish immutable but that contains a collection referencing mutable instances) requires to write more code (to read/to maintain/to test) and to perform more processing (so slower to execute).
If Student was an immutable class, the original getTutees() and the original constructor would be enough.
Proper way is to make an object immutable is to:
Declare the object final
Do not provide setter methods
Make all fields private
Make mutable fields final
Use deep copy in the constructor
Clone objects in getter methods, so you don't return actual reference.
Do you really need to return the Set of Students? If you really need that you can hide that by using an interface that provides only getters, something like
interface IStudent {
public String getName();
public String getCourse();
}
class Student : implements IStudent { ...}
and in your Tutor you return Set<IStudent>
To make the Tutor class immutable, you should use the "final" modifier on all the fields inside a Tutor, not on the Tutor's class definition.
Java SE 16
You can use JEP 395: Records feature, introduced as part of Java SE 16, to create an immutable class without requiring much ceremony.
If you have already gone through the above link, you must have figured out that you can do it simply as
record Tutor(String name, Set<Student> tutees) { }
What you get in turn are:
A final class Tutor.
A canonical constructor whose signature is the same as the header, Tutor(String name, Set<Student> tutees).
private final fields, name and tutees and their corresponding public accessor method with the same name and return type.
Automatically created equals, hashCode and toString methods.
Demo:
Student.java
record Student(String name, String course) { }
Tutor.java
import java.util.Set;
record Tutor(String name, Set<Student> tutees) { }
Main.java
import java.util.Set;
class Main {
public static void main(String[] args) {
Set<Student> cscStudents = Set.of(
new Student("Harry", "Java-8"),
new Student("Tina", "Java-9"),
new Student("Andy", "Java-11")
);
Set<Student> scienceStudents = Set.of(
new Student("Tony", "Phy"),
new Student("Kerry", "Chem"),
new Student("John", "Bio")
);
Tutor t1 = new Tutor("Mark", cscStudents);
Tutor t2 = new Tutor("Robin", scienceStudents);
Tutor t3 = new Tutor("Mark", Set.of(
new Student("Andy", "Java-11"),
new Student("Harry", "Java-8"),
new Student("Tina", "Java-9")
)
);
System.out.println(t1);
System.out.println();
System.out.println(t1.tutees());
System.out.println();
System.out.println("Students of " + t1.name() + ":");
t1.tutees()
.stream()
.forEach( t -> System.out.println(t.name()) );
System.out.println();
System.out.println(t1.equals(t2));
System.out.println(t1.equals(t3));
}
}
Output:
Tutor[name=Mark, tutees=[Student[name=Andy, course=Java-11], Student[name=Harry, course=Java-8], Student[name=Tina, course=Java-9]]]
[Student[name=Andy, course=Java-11], Student[name=Harry, course=Java-8], Student[name=Tina, course=Java-9]]
Students of Mark:
Andy
Harry
Tina
false
true
I have cut out the code to shorten the page but I'm asking how do I change personInterests into its own class. Apologies for the vague question but essentially I want to change personInterests in my Person class to a class where personInterests has multiple variables.
import java.util.ArrayList;
import java.util.*;
public class Person{
private String personName;
private String[] personInterests = new String[3];
public Person(String personName, String[] personInterests){
this.personName = personName;
this.personInterests = personInterests;
}
public void setInterests(String[] personInterests){
this.personInterests = personInterests;
}
public String[] getInterests(){
return personInterests;
}
public String getName(){
return personName;
}
public String toString(){
String result = getName() + " ";
for (String interests : personInterests) {
result += interests + " ";
}
return result;
}
}
This was my idea of how it would work just not sure how I would use this class and call it later on.
import java.util.ArrayList;
import java.util.*;
public class Interests {
private int interestDangerRating;
private String interestName;
private ArrayList<Interests> interestsList = new ArrayList<>();
public Interests (int interestDangerRating ,String interestName){
this.interestDangerRating = interestDangerRating;
this.interestName = interestName;
}
public void addInterests(Interests p){
interestsList.add(p);
}
Interests getInterests(int i){
return interestsList.get(i);
}
}
Any help is appreciated, as I said this code has mostly been taken out and this was an old project already completed just wanted to see if I could change some of the features.
OK so here's what I would do to clean this up for you and make it work. Firstly, think about what you are trying to do. You want to create a Person who has multiple Interests, right? So the Interest class, going by your above example, can be changed to be a typical Java object class as follows:
public class Interest {
private int dangerRating;
private String name;
public Interest (int dangerRating, String name) {
this.dangerRating = dangerRating;
this.name = name;
}
public int getDangerRating() {
return dangerRating;
}
public String getName() {
return name;
}
}
So now we've an Interest class set up where you can set a name for your interest and a danger rating. What we need to do, now, is edit your Person class so as you can store a list of interests for each Person you create.
import java.util.ArrayList;
public class Person{
private String name;
private ArrayList<Interest> interests = new ArrayList<Interest>();
public Person(String name, ArrayList<Interest> interests) {
this.name = name;
this.interests = interests;
}
public void addInterest(Interest newInterest) {
interests.add(newInterest);
}
public Interest getInterest(int indexOfInterest) {
return interests.get(indexOfInterest);
}
public ArrayList<Interest> getInterests() {
return interests;
}
public String getName() {
return name;
}
public String toString() {
String result = getName() + " ";
for(Interest interest : interests) {
result += interest.getName() + "(" + interest.getDangerRating() + ")" + " ";
}
return result.trim();
}
}
This allows you to set an initial list of all interests for your new Person and, from there, you can add new interests, get all interests or get any individual interest.
Hope this helps to clarify for you how this should all fit together!
So now it's time to instantiate everything. Lets create some Interestobjects which we will use:
Interest golf = new Interest(1, "golf");
Interest swimming = new Interest(3, "swimming");
Now lets assume we want two people called John and Mary. John likes golf and swimming while Mary only likes swimming. We'd then create their list of Interest as follows:
ArrayList<Interest> johnsInterests = new ArrayList<Interest>();
johnsInterests.add(golf);
johnsInterests.add(swimming);
ArrayList<Interest> marysInterests = new ArrayList<Interest>();
marysInterests.add(swimming);
And finally, we'd then create our two Person objects which will include the persons name and interests list.
Person john = new Person("John", johnsInterests);
Person mary = new Person("Mary", marysInterests);
And voila!
First, make an Interestclass:
public class Interest {
private int interestDangerRating;
private String interestName;
// .. getters and setters
}
then in the Personclass get rid of private String[] personInterests = new String[3];
and replace it by:
private ArrayList<Interest> interestsList = new ArrayList<>();
You're getting there with the logic of your Interests class, but it needs a few changes
import java.util.ArrayList;
import java.util.*;
public class Interests {
private int interestDangerRating;
// Is this a unique name for the entire class? If yes then no worries, but if not
// then its not needed, you've already got a list of interest names below
private String interestName;
// Change the array list to hold Strings, it's a list of words
private ArrayList<String> interestsList = new ArrayList<>();
public Interests (int interestDangerRating ,String interestName){
this.interestDangerRating = interestDangerRating;
this.interestName = interestName;
}
public void addInterest(String p){ // Again, change this to String
interestsList.add(p);
}
String getInterest(int i){ // Change this to return a String, since we changed the ArrayList above
return interestsList.get(i);
}
}
There's alot more you need to think about with this class too. How do you know how many interests are in the list, should there be a length variable? Or what about a method that returns the entire list of interests rather than just 1?
Also, there's only one interestDangerRating being set in this class; if each interest has a different danger rating, should't you be adding a danger rating for every interest?
In terms of accessing your new class, you'll need to create a class in your code by:
Interests variableName = new Interests(1, "football");
I have randomly chosen '1' and 'football' above, since they are in your Interest class' constructor. The way your class is built, you cannot use it without providing an int and a String when the object is made
Finally, to call methods on your class, you use the variable created above to call its methods:
variableName.addInterest("basketball");
String interest = variableName.getInterest(1);
If you're struggling, I recommend looking at a simple java tutorial online. instatiating java classes and calling their methods like this are fundamental concepts in Java :)
Unsure on how i'm supposed to add to an array, i've been asked to fill the array from a test file but define it in class Patient. Any ideas?
public class Patient
{
private String name;
private int id;
private int current = 1;
public Patient(String name, int id)
{
this.name = name;
this.id = id;
Patient[] patient = new Patient[100];
String[] Observations;
System.out.print(patient[0]);
}
public String addPatient(String name,int id)
{
Patient[current-1] = new Patient(name,id);
}
}
// extract from class PatientRecordSystem
public void addPatient()
{
String name = "James";
int id = 10122;
Patient patient = new Patient(name, id);
}
Your problem is that you are defining that list (or array) to hold Patient objects within the constructor of your Patient class.
That is simply wrong on many levels. First of all - one "Patient" should be exactly that - the representation of a single patient. When you go to the doctor and become a patient ... are you asked to know about 100 other patients around?! Then: that array that you define in the constructor ... just lives during the execution of the constructor. It simply goes away as soon as a call
Patient newPatient = new Patient( ... )
returns.
In other words: you want to think of another class that is responsible for "managing" multiple patients. And then you create "patient objects"; and tell the manager about them. And that "manager" is then using an array (or better some more dynamic List) in order to keep track of "managed" patients.
Whatever Andrew said is correct , just making it easy for you. Use below code
public class Patient
{
private String name;
private int id;
private int current = 1;
private Patient[] patient = new Patient[100];
public Patient(String name, int id)
{
this.name = name;
this.id = id;
String[] Observations;
System.out.print(patient[0]);
}
public String addPatient(String name,int id)
{
patient[current-1] = new Patient(name,id);
}
}
// extract from class PatientRecordSystem
public void addPatient()
{
String name = "James";
int id = 10122;
Patient patient = new Patient(name, id);
}
First you need to declare the array.
You can do something like:
Patient[] patients = new Patient[100];
if you know the size of the array.
If you want to build a dynamic array, because you don't know how many elements you are going to have, you can do something like that.
List<Patient> patients = new ArrayList<Patient>();
Then you can assign values to the array:
If you have declared a fixed array you can do something like that:
patients[0] = new Patient(name, id);
On the other hand, if you have declared a dynamic array, the code would look like:
patients.add(new Patient(name, id));
Guys this is my membership class so far, i am struggling to create a method that finds the full members details that i have given just using a uniqueId finder. Please help.
public class Membership {
private String FirstName;
private String LastName;
private int memberId;
private String listOfMembers;
private int uniqueId;
private long phoneNumber;
public Membership(String FirstName, String LastName, int uniqueId,
long phoneNumber)
{
this.uniqueId = uniqueId;
this.FirstName = FirstName;
this.LastName = LastName;
this.phoneNumber = phoneNumber;
}
public String getMember()
{
return FirstName + LastName;
}
public String getlistOfMembers()
{
return (FirstName + LastName);
}
public int getId()
{
return uniqueId;
}
public void MemberId (int Id)
{
System.out.println("Id" + Id);
}
public String getMemberDetails ()
{
System.out.println("Member Id: " + uniqueId);
System.out.println("first name: " + FirstName);
System.out.println("LastName: " + LastName);
System.out.println("Member phone number: " + phoneNumber);
return listOfMembers;
}
}
This is what i have done so far.
Issues:
You've got user interface code where it doesn't belong. I would remove all System.out.println statements from this class and instead leave it in a UI class or main method (if very simple).
In particular, getter methods should return field values, and should not have System.out.println statements
I'm not sure why this class has a listOfMembers field, or why it's just a String. You look to be trying to combine Member and Membership together in one single class -- Don't do this.
I'd name this class Member since it holds information for just a single Member.
If I needed a Membership class, it would instead hold an ArrayList<Member>
And it would have a public Member getMember(int id) method that would return the item in the list above that shares the id passed into the method. A simple for loop that iterated through the list, comparing id's would suffice.
To add on Hovercraft's answer with an example.
You have your class handling all the members, very basic implementation of it.
public class Membership {
private final Map<Integer, Member> members = new HashMap<>();
public void addMember (Integer uniqueId, Member member) {
members.put (uniqueId, member);
}
public void getMember (Integer uniqueId) {
return members.get (uniqueId);
}
...
}
Then you have the Members themselves like this, more fields can be added as you want them.
public class Member {
private String firstName;
private String lastName;
public Member (String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName () {
return firstName;
}
...
}
This is a very basic, but strong, feature in OOP to use.
Again see Hovercraft's answer as it provides all the details. If they were to edit/remove I will update this one.
Map vs List
One minor thing is I'd vote against using an ArrayList<E> to store the Members. If you add to the implementation that you can remove users the uniqueId will shift from user to user. Instead I would be for making sure that you are not adding to an existing user.
If you want to keep it simple and just get going, an ArrayList<E> works, do know the problem you might get in the feature, an uniqueId is not necessarily tied to a Member.
"I am quite new to java and have never come across "map" can you please explain what it is?"
"An object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value." - From: Documentation.
Instead of working with direct indexes as you do in an Array:
arr[5]; // here you get the value at index position 5.
Or like a List:
list.get(5); // here you get the fifth element, it can be stored (almost) anywhere in the memory, before or after 4, doesn't matter, as 4 knows where 5 is.
And for a Map:
map.get(5); // you get the object stored at 5, there might not be a 3 or 4 in the Map. You can store any Objects as anything. A String is another example of a common key.
I would suggest to use Map and use id as key of Map and store object of Membership as Value,thereby easy to retrieve and store also.
Something similar to this,
Map<Integer,Membership> map = new HashMap<Integer,Membership>();
Membership m = new Membership("First", "LastName", 1,1234567890);
map.put(m.getId(), m);
To get member by id,
System.out.println(map.get(id).getMemberDetails());