Create new objects from ArrayList<E> items [duplicate] - java

This question already has answers here:
Why do we need copy constructor and when should we use copy constructor in java
(8 answers)
Closed 3 years ago.
I need to create several new objects from an ArrayList. Suppose my list is:
ArrayList<InvVoucher> list = .....;
int index = 0;
InvVoucher vch1 = list.get(index);
InvVoucher vch2 = list.get(index);
InvVoucher vch3 = list.get(index);
Here vch1, vch2 and vch3 are holding the same object reference. How can I make all of them independent? How can I get three different copy of InvVoucher?

One way would be to implement a copy constructor in IntVoucher as suggested in the comments.
public class IntVoucher {
public IntVoucher(IntVoucher original) {
this.field1 = new Field1(original.field1);
...
}
private Field1 field1;
...
}
That way you can do
IntVoucher vch1 = new IntVoucher(list.get(index));
Another possibility is overriding the clone method in IntVoucher and having it implement the java.lang.Cloneable interface.
public class IntVoucher implements Cloneable {
// note: change from protected to public if needed
protected IntVoucher clone() {
IntVoucher clone = new IntVoucher();
clone.field1 = new Field1(this.field1);
...
return clone;
}
private Field1 field1;
...
}
Read more on shallow / deep copying in Java. There are lots of complete examples if this isn't enough.

Related

Assigning ArrayList object to Instance variable - java

The code snippet below is part of some code I am reading for an assignment but I cant understand the role of the copy variable in the snippet or what it does. I know its an instance of the Sample class, but why it is then assigned an ArrayList is not clear to me.
public class Sample implements Var{
private List lst1;
private List lst2;
public Sample() {
super();
}
public Sample(List lst1) {
this();
this.lst1 = lst1;
}
public List getLst1() {
return lst1;
}
public void setLst1(List lst1) {
this.lst1 = lst1;
}
#Override
public Var copy(){
Sample copy = new Sample(lst1);
copy.lst2 = new ArrayList(lst2);
return copy;
}
#Override
public void randomize(){
}
}
In fact the error message is explicit to show that you can't iterate over the variable copy because you haven't implemented the Iterable interface which allows you to do it. If you insist to loop over it and to have functions allowing you to do so: just visit this link Java Generics - Implementing the Iterable Interface where you can for exemple (if this is what you want) iterate over the elements of the two lists of an instance lst1 and lst2

Should i use setters that include additional logic from my constructor? [duplicate]

This question already has answers here:
Why it is not a good idea to call Set method from constructor?
(6 answers)
Closed 6 years ago.
I have a class that needs to reset its internal iterator on a list whenever a new list is set:
public class ListElementReceiver implements ElementReceiver {
private List<Element> elements;
private Iterator<Element> elementIter;
public void reset() {
elementIter = elements.iterator();
}
public void setElements(List<Element> elements) {
this.elements = elements;
reset();
}
}
It's basically just a wrapper around a list and its iterator so i can use it with my given Interface ElementReceiver. The problem i have is building the constructors for this class. Which of the two approaches is preferable?
// Approach 1: Duplicate logic, independant of Setter
public ListElementReceiver() {
elements = new List<Element>();
reset();
}
public ListElementReceiver(List<Element> elements) {
this.elements = elements;
reset();
}
//Approach 2: Make dependant on Setter
public ListElementReceiver() {
setElements(new List<Element>());
}
public ListElementReceiver(List<Element> elements) {
setElements(elements);
}
From a constructor, you should not call methods (including setters) that can be overridden by subclasses. That can lead to code in the subclass being executed before the subclass is fully constructed, which can cause bugs that are difficult to track down.
It's okay to call private or final methods (provided they don't, in turn, invoke any overrideable code), or to call methods in a final class, but that doesn't look like what you have here.
You can avoid duplicate logic with your first approach by having one constructor invoke another:
public ListElementReceiver() {
this(new ArrayList<>());
}
public ListElementReceiver(List<Element> elements) {
this.elements = elements;
elementIter = elements.iterator();
}

Java - does the collection always change when I get a value and change

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);
}
}

How to create different objects depending on the parameter passed? [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 6 years ago.
I have a use-case like this:
Based on the parameter passed - I have to create an object corresponding to it but the underlying functionality remains same.
public void selectType ()
{
String type = "ABC";
publishType(type);
}
public void publishType(String type)
{
if (type.equals("ABC"))
ABCtype publishObject = new ABCtype();
if (type.equals("XYZ"))
XYZtype publishObject = new XYZtype();
publishObject.setfunctionality();
}
What is a better way to approach this?
Which design pattern does it fall in?
Another doubt I have is - how to initialize publishObject?
It gives an error like this.
but the underlying functionality remains same
you maybe consider design suing interfaces..
Do some nice Archi- Design like:
define an interface, and 2 classes that implement the interface, then
declare an object foo and initialize it according to the parameter..
Example:
interface IObject{
//methods here
}
class A implements IObject{}
class B implements IObject{}
public void selectType ()
{
IObject foo = getObject(1);
}
public IObject getObject(int type){
if (type ==1){
return new A();
}else{
return new B();
}
}

Get every references to some object in Java [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
All references to an object
I'm looking for a way to get a list of class/instance members who have a reference to some variable, in Java.
For instance, for this case:
public class MyClass {
public LinkedList list;
}
public class MyOtherClass {
public LinkedList list;
}
public class Program {
public static void main(...) {
LinkedList list = new LinkedList();
MyClass c1 = new MyClass();
MyOtherClass c2 = new MyOtherClass();
c1.list = list;
c2.list = list;
}
}
At the end of the program we have 3 references for the LinkedList created on my first line of code in Program.main:
Program.main.list
MyClass.list
MyOtherClass.list
While the first one is a local variable (doesn't care for me), the others are instance fields. In this case, what I need it's some way to get, for 2. and 3., the reference to the objects (MyClass and MyOtherClass) and the field name that have the reference for the LinkedList created on line 1.
How can I do that?
"Pure" Java solution: not sure if it works for you, but if you can afford to wrap your object and access it only via wrapper, then you can try WeakHashMap:
public class Wrapper {
private final Object yourObject;
private final WeakHashMap<Object, Object> accessors = new WeakHashMap<Object, Object>();
public Wrapper(Object yourObject) {
this.yourObject = yourObject;
}
// add synchronized if you want thread-safety.
public Object getYourObject(Object accessor) {
accessors.put(accessor, accessor);
return yourObject;
}
// add synchronized if you want thread-safety.
public Object[] getAccessors() {
return accessors.keySet().toArray(new Object[accessors.keySet().size()]);
}
}

Categories

Resources