public class Employee
{
private String name;
private String department;
private ArrayList<Employee>job= new ArrayList();
// just want to add getter and setter for this ArrayList
public void setJob(Employee j)
{
job.add(j);
// this is my setter
I want to be able to add later on as many 'job' as I want by extending the arraylist
While you can have setters and getter of List type, you should think carefully about their implementation, because most lists are mutable.
For instance, assume that you want to validate that the jobs list is not empty.
public void setJob(List<Employee> jobs) {
if (jobs.isEmpty()) throw new RuntimeException();
this.job = jobs;
}
Now the following code produces an employee without jobs:
Employee e = ...;
e.setJobs(jobs);
jobs.clear();
//the employee now has no jobs :-(
You can avoid this issue by making a defensive copy
public void setJob(List<Employee> j) {
this.job = new ArrayList<>(j);
}
The same applies to the getter. If you implement it as:
public List<Employee> getJobs() {
return this.jobs;
}
you are allowing the caller to modify the private job list without invoking the corresponding setter: myEmployee.getJobs().clear().
In this case, you may return an unmodifiable list instead of returning the inner object.
public List<Employee> getJobs() {
return java.util.Collections.unmodifiableList(this.jobs);
}
Ordinarily for a collection or array you would use addJob, removeJob and getJobs instead of a get/set pair.
Related
public enum Test implements IsSerializable {
FOOD("FOOD", getFoodItems()),//---Getting Error here
HOTEL("HOTEL", getHotels());//---Getting Error here
private String name;
static final List<String> categories = new LinkedList<String>();
Test(String name) {
this.name = name;
}
public List<String> getCategories() {
return this.categories;
}
private List<String> getFoodItems(){
categories.add("Food item1");
categories.add("Food item2");
return categories;
}
private List<String> getHotels(){
categories.add("Hotel 1");
categories.add("Hotel 2");
return categories;
}
}
I am getting error while creating this Enum. I am new to this type Enum . Can anyone help to make this work?
3 main things:
1. getFoodItems() and getHotels() should be static.
The methods need the existing enum to exist and do not even use anything in the enum.
2. don't declare categories as a static attribute..
You use the same categories object(or references to the same object) because it is static. Remove the static keyword before it in order to make it a member attribute. Each object should have it's own list and this is not possible if it is static.
3. create the List inside the method and give it to the constructor
You call the constructor with 2 parameters: the name and the List but the constructor does only accept the name. Create the categories object inside the methand and return it to the constructor.
3 additional improvements from #Holger (see the comments)
4. Think twice before handing out references to mutable lists.
If you pass a mutable list to a method, that method can change the list which could lead to bugs that may be difficult to find.
5. The name is entirely obsolete as there is no getter for it and its value matches the intrinsic name() anyway.
You may want to add it in any case but enumerations already have a method name() that returns the name of the enum.
6. Don’t use LinkedList when you don’t need its special features (in other words, never use it), but rather, use an ArrayList or even better, List.of(item1, item2), to create an immutable list.
ArrayList is more performant that LinkedList in general because it is based on an array and LinkedList is a linked list(as the name says) that has to create an object for every element containing reference to it's neighbours. That is an advantage if you need to add elements in the middle (or the start) of the list or if you need Queue or Dequeue functionality.
public enum Test implements IsSerializable {
FOOD("FOOD",getFoodItems()),//---Getting Error here.
HOTEL("HOTEL",getHotels());//---Getting Error here
private String name;
private final List<String> categories;
private Test(String name,List<String> categories) {
this.name = name;
this.categories=categories;
}
public List<String> getCategories() {
return this.categories;
}
private static List<String> getFoodItems(){
List<String> categories = new LinkedList<>();
categories.add("Food item1");
categories.add("Food item2");
return categories;
}
private static List<String> getHotels(){
List<String> categories = new ArrayList<>();
categories.add("Hotel 1");
categories.add("Hotel 2");
return categories;
}
}
[Edit]
Please also take note of the answer from boot-and-bottet
Static methods should work, if the constructor is fixed. If the list of items is small, why not declare them inline?
public static enum Test implements IsSerializable {
FOOD("FOOD", "Food item1", "Food item2"),
HOTEL("HOTEL", "Hotel 1", "Hotel 2");
private final String displayName;
private final List<String> categories;
Test(String displayName, String... categories) {
this.displayName = displayName;
this.categories = List.of(categories);
}
public String displayName() {
return displayName;
}
public List<String> getCategories() {
return categories;
}
}
Core issue is that enum initialized in static, and from that context you can't reference non-static items (fields, methods).
Also you don't have place for those lists in your enum - constructor accepts only name param.
You could try to use List.of("Food item1", "Food item2") instead for example and adding new field.
Let's say you have different employees but each employee class has a salary() method. How can I make these different objects I made and put in an ArrayList use the method salary()?
public void betaalSalarissen(){
for(int counter = 0;werknemers.size()>counter;counter++){
Class objectClass = werknemers.get(counter).getClass();
**objectClass.salaris();** //this won't work, help please!
}
}
public void neemInDienst(Object persoon){ //objects from different classes, different employees
werknemers.add(persoon);
}
There's no reason to try to get the class; just use polymorphism.
public class Employee {
public double salaris() { ... }
}
public class CommissionedEmployee extends Employee {
#Override
public double salaris() { ... }
}
List<Employee> employees = new ArrayList<>();
// add some employees of whatever subtype(s)
for (Employee e : employees) {
e.salaris();
}
the quick solution here is to cast the result from werknemers.get(counter)``to yourEmployee` class (class name just guessed)
((Employee)werknemers.get(counter)).salaris();
but in the long run you should apply a generic parameter to the collection variable and the methods parameter:
private Collection<Employee> werknemers = new ArrayList<>();
public void neemInDienst(Employee persoon){ //objects from different classes, different employees
werknemers.add(persoon);
}
then you can simply iterate over the element without cast just as ChiefTwoPencils suggested.
I'm writing a program now in Java which is kind of like a server. I got a MemberController, in MemberController it gets Members from the database OR from the cache (to speed up process). This is an example of how it looks:
public class MemberController {
private final TMap<Integer, Member> members;
public MemberController() {
this.members = new THashMap<>();
}
public Member getMemberByID(int id) {
if (members.containsKey(id)) {
return members.get(id);
}
// GET DATA FROM DB
members.put(ID, MEMBER);
return MEMBER;
}
Now, Member contains a BadgeController object, which contains a TMap for the badges. Example of Member:
public class Member {
// FIELDS OF MEMBER HERE
private BadgeController badgeController;
public Member(ResultSet set) {
// SET FIELDS
}
public void InitOtherData() {
badgeController = new BadgeController(id);
}
public BadgeController getBadgeController() {
return badgeController;
}
And BadgeController:
public class BadgeController {
private final int memberId;
private final TMap<String, Badge> badges;
public BadgeController(int memberId) {
this.memberId = memberId;
this.badges = new THashMap<>();
// LOAD FROM DB
}
public Badge getBadge(String code) {
return badges.get(code);
}
Now, I was wondering a few things (all actually refer to the same I guess):
If I get a Member from members, like members.get(1), and I edit the object, like this:
Member member = members.get(1);
member.setId(1);
Will this edit the id inside the TMap as well? So if I do members.get(1) again, it has the updated value?
If I have the member from above, and I change a value of the Badge, for example I do:
Member member = members.get(1);
member.getBadgeController().getBadge('500Members').setActive(true);
Will this result in true being printed?
System.out.println(members.get(1).getBadgeController().getBadge('500Members').getActive());
I hope my explaination is good enough. It's hard for me to explain it. I'm sorry.
Member member = members.get(1); does not copy the object but just makes a shortcut (reference). Changing member affects the item in your set as well.
To create an effective copy you have to make your object inherit from the Cloneable interface and call the clone() method on it to get a copy.
you need to DEEP copy object by:
implementing clone interface
create a copy constructor (simplest solution as clone)
examples:
// simple copy constructor
public SomerController(SomeController original) {
members = orginal.clone();
}
// more advanced copy constructor
public SomeController(SomeController original) {
Set<Map.Entry<String, String>> entries = orginal.members.entrySet();
members = new HashMap<String,Class>();
Iterator<Map.Entry<String, Class>> iterator = entries.iterator();
while(iterator.hasNext()) {
Map.Entry<String, String> next = iterator.next();
String key = next.getKey();
// if class contains a collections ( maps, arrays )
// you need to provide a copy here
// ensure to copy whole tree of references
Class value next.getValue();
map.put(key,value);
}
}
I have the following classes:
public class School{
List<ClassRoom> classRooms;
}
public class ClassRoom{
List<Student> students;
}
public class Student{
String name;
long typeId;
}
I need to get the whole students within the given class roomS that has typeID=123
Expected result:
List filteredStudent=classRoomList.filterByStudentTypeID(typeIdToSearchFor)
I don't need to write some dirty code and loops.
I need to take advantage of existing libraries.
I found out Google Guava.
I found out a method at guava that searches by the the whole reference ... instead I need to search using the attribute, typeId
Collection<Student> filtered =Collections2.filter(students, Predicates.equalTo(s1));
Any ideas!
Since you are using Guava, you can use a custom predicate:
final long typeIdToSearchFor = ...;
Collection<Student> filtered = Collections2.filter(students,
new Predicate<Student>() {
#Override
public boolean apply(Student s) {
return s.typeId == typeIdToSearchFor;
}
}
);
Note that typeIdToSearchFor must be final in the scope of the call to filter because it is being referenced by the (anonymous) Predicate subclass.
I am having problems with the copy constructor of a Linkend List in Java.
The list I am trying to copy has a size of 3, when I use the copy constructor the list is empty.
When I try this with the clone method everything works great.
I have look a this for a quite a while and I get the feeling it is so obvious. I just
dont see it, here is the code.
public class Employee {
private String name;
private double salary;
public Employee(String name, double salary){
this.name = name;
this.salary = salary;
}
public void setname(String name){
this.name = name;
}
public void setsalary(double salary){
this.salary = salary;
}
public String getname(){
return this.name;
}
public double getsalary(){
return this.salary;
}
}
public class Main {
public static void main(String[] args) {
Employees employees = new Employees();
employees.add(new Employee("Employee1", 2500.00));
employees.add(new Employee("Employee2", 2400.00));
employees.add(new Employee("Employee3", 2000.00));
Employees employeesCopy2 = new Employees(employees);
Employees employeesCopy = (Employees) employees.clone();
System.out.println(employees.size());
System.out.println(employeesCopy2.size());
System.out.println(employeesCopy.size());
}
}
import java.util.LinkedList;
public class Employees extends LinkedList<Employee> {
private static final long serialVersionUID = 1L;
private LinkedList<Employee> employees;
public Employees(){
employees = new LinkedList<Employee>();
}
public Employees(Employees w){
employees = new LinkedList<Employee>(w);
}
public void addWerknemer(Employee w){
employees.add(w);
}
}
EDIT
This is homework, but when I wanted to add the tag is showed that the tag was no longer is use.
I think this:
public class Employees extends LinkedList<Employee> {
private LinkedList<Employee> employees;
will create a world of confusion. You're both extending a list, and within that class you're maintaining a separate list. When you call addWerknemer() you add to the inner list. What happens when you call get() ? Since you've not overridden this, you're calling get() on the base class, and that's a different list!
Without inspecting the rest of your code, I suspect this is a fundamental source of problems.
You have two choices:
Employees extends List
Employees contains a List
I would prefer the second. You can change the underlying collection (e.g. a Set, perhaps a Map for better lookup performance) and not change the exposed interface.
You are extending LinkedList, but also have a LinkedList inside that extension. Initially you use the add method to add Employee instances, so they get added to the Employees list itself, but when you use the copy constructor, you copy those employees to the employees field inside your Employees class.
When you call the size() method, it will use the LinkedList of the Employees object itself, so in the first list it is 3, but on the second it is 0 as now the employees are in the contained list and not in the object itself.
In this case you probably should not extend LinkedList. Or if you do, then don't use a separate field like employees which also contains a LinkedList.
Your confusion comes from the fact, that Employees both is a list and contains a list. When you use
employees.add(new Employee("Employee1", 2500.00));
you add the employee to the outer list. When you use
employees.addWerknemer(new Employee("Employee1", 2500.00));
you add the employee to the inner list. Since you have overwritten the constructor Employees(Employees es), this will not clone the outer list, but only the inner. And since you haven't overwritten clone(), it will clone the outer list, but not the inner. This is rather messy and also most probably not intended by you. I therefore propose one of the following changes:
1. [Preferred] Employees only contains a list and not extends one
Skip the extends LinkedList<Employee> and only work with an internal list. You will have to use your method addWerknemer(Employee emp) to add to your list (or change it's name to add). You will have to implement size and clone as well as other methods that you wish to use. If you want to be really clean about this, you can even make the class implement List or implement Collection or so. This way you can still treat your class as a java.util.Collection. I don't think that this would be neccessary in your case though. Also you would need to implement all of the interfaces methods (there are many). An example implementation would look like this. You still have to implement size, etc.
public class Employees /*implements List<Employees>*/ {
private static final long serialVersionUID = 1L;
private LinkedList<Employee> employees;
public Employees(){
employees = new LinkedList<Employee>();
}
public Employees(Employees w){
employees = new LinkedList<Employee>(w);
}
public void add(Employee w){
employees.add(w);
}
public Employees clone() {
return employees.clone();
}
// add more methods as you need them (like remove, get, size, etc)
}
2. Employees only extends LinkedList and doesn't contain one
Throw away your methods addWerknemer(Employee emp) and the copy constructor Employees(Employees) as well as your internal list. This way you will not overwrite the existing implementations of LinkedList. This approach is more or less useless because you basically just rename LinkedList to Employees and add/change nothing. Therefore I wouldn't recommend this approach.