I wonder if there is a method that checks whether my new instance has been already created and added to my instances in Java...
Like ;
Instance instance = new Instance(i, vals);
if(instances.contains(instance) == false) { //or hasInstance maybe
instances.add(instance);
}
I understand, that you want for two objects x1 and x2 with x1.equals(x2) that x1 is the same instance (x1 == x2).
One needs to do something like this:
private Map<Instance, Instance> identityMap = new HashMap<>();
public Instance unique(Instance instance) {
Instance first = identityMap.get(instance);
if (first == null) {
first = instance;
identityMap.put(instance, instance);
}
return first;
}
Instance instance = new Instance(i, vals);
instance = unique(instance);
The reason is, that you want to maintain the first instance, to be used by all.
By the way - for other purposes:
Set<Instance> instances = ...;
Instead of
if (!instances.contains(instance)) { // if not instances contains
one could use code like
if (instances.add(instance)) {
// Added, hence new...
} else {
// Not added, hence already existing...
}
Related
I have a method whose some parts of are repetitive. I managed to split the code in a way that the original method uses smaller methods many times. The problem is that when I pass some values as params to those new smaller methods and work with them, original values don't get updated. The actions I do are: value incrementation or removing items from arraylist. How do I update the original values using the smaller methods, not only the references? The only possible solution I came up with is to create a new class where I could have a setter for those values and update them. But are there easier/straightforward ways to solve it?
Part of the main method:
int numberOfBlocks = 0;
int currentBlock = 0;
int currentTime = 0;
ArrayList<Request> queue = new ArrayList<Request>();
if(queue.size != 0) {
updateStatus(queue, currentBlock, numberOfBlocks);
}
if(something else happens) {
removeFinished(queue, currentBlock);
}
Smaller methods:
private void updateStatus(ArrayList<Request> queue, int currentBlock, int numberOfBlocks) {
if (queue.get(0).getBlock() > currentBlock)
currentBlock++;
else
currentBlock--;
numberOfBlocks++;
}
private void removeFinished(ArrayList<Request> queue, int currentBlock){
if (queue.get(0).getBlock() == currentBlock) {
queue.remove(0);
}
}
First of all, if you pass a parameter in order for it to be changed in the method, your method should return the changed value, this will resolve your issue. If more then one value needs to be changed, then you are correct, primitives are passed y value and the invoking method doesn't see the changes made in the invoked method. So you should encapsulate those values in a wrapping class with setters and getters like you wanted to. That alone will resolve your problem. But also it would make sense for your method to return that class since it is modified. This is just a good stile
If the smaller methods are in the same class as the main method, simply don't pass them as parameters and the methods will use the class's fields. This is non-thread safe, but your class is non-thread safe already anyway.
class MyClass
{
int numberOfBlocks = 0;
int currentBlock = 0;
int currentTime = 0;
ArrayList<Request> queue = new ArrayList<Request>();
void myMainMethod() {
if(queue.size != 0) {
updateStatus();
}
if(something else happens) {
removeFinished();
}
}
private void updateStatus() {
if (queue.get(0).getBlock() > currentBlock)
currentBlock++;
else
currentBlock--;
numberOfBlocks++;
}
private void removeFinished() {
if (queue.get(0).getBlock() == currentBlock) {
queue.remove(0);
}
}
Hello everyone I'm writing a Java program where I need to copy the values of an old object into a new one (the two must be separated, if I chance one, the other must not be affected);
Once the copy is done the data should be displayed on Jtable, however the 2 object created seems to be linked(if I try to change one the other get modified too)
I suspect the problem is this method :
public void CopiatoreDiArea(Area nuova, Area daCopiare){
nuova.setNome(daCopiare.getNome());
nuova.setInter(daCopiare.getInter());
nuova.setRischioInerente(daCopiare.getRischioInerente());
nuova.setRischioResiduo(daCopiare.getRischioResiduo());
nuova.setControlli(daCopiare.getChecklists());
nuova.setStrategicita(daCopiare.getStrategicita());
nuova.setRischiosita(daCopiare.getRischiosita());
nuova.setMediaHpReato(daCopiare.getMediaHpReato());
nuova.setProbabilitaInerente(daCopiare.getProbabilitaInerente());
nuova.setEsposta(daCopiare.isEsposta());
nuova.setStrumentale(daCopiare.isStrumentale());
nuova.setCommento(daCopiare.getCommento());
nuova.setCondivisa(daCopiare.isCondivisa());
if (daCopiare.getNomeCompleto() != null){
nuova.setNomeCompleto(daCopiare.getNomeCompleto());
}
else{
nuova.setNomeCompleto(daCopiare.getNome());
}
if (daCopiare.getInterCompany() != null){
nuova.setInterCompany(daCopiare.getInterCompany());
}
if (daCopiare.getArticoli() != null || daCopiare.getArticoli().size() != 0){
nuova.setArticoli(daCopiare.getArticoli());
}
}
If this is the wrong way, how can I accomplish that?
How do you create the new instance of nuova object?
You have to make a new instance of it, if you created the new object with the reference of the oldest they will be linked and every change in the one will be reflected in other.
If you call the method as following:
CopiatoreDiArea(new Area(), oldArea)
Your code should work as the new 'Area' has all the attributes the other object has without any references being made to the new Area.
Try this:
public Area CopiatoreDiArea(Area daCopiare){
Area nuova = new Area();
nuova.setNome(daCopiare.getNome());
nuova.setInter(daCopiare.getInter());
nuova.setRischioInerente(daCopiare.getRischioInerente());
nuova.setRischioResiduo(daCopiare.getRischioResiduo());
nuova.setControlli(daCopiare.getChecklists());
nuova.setStrategicita(daCopiare.getStrategicita());
nuova.setRischiosita(daCopiare.getRischiosita());
nuova.setMediaHpReato(daCopiare.getMediaHpReato());
nuova.setProbabilitaInerente(daCopiare.getProbabilitaInerente());
nuova.setEsposta(daCopiare.isEsposta());
nuova.setStrumentale(daCopiare.isStrumentale());
nuova.setCommento(daCopiare.getCommento());
nuova.setCondivisa(daCopiare.isCondivisa());
if (daCopiare.getNomeCompleto() != null){
nuova.setNomeCompleto(daCopiare.getNomeCompleto());
}
else{
nuova.setNomeCompleto(daCopiare.getNome());
}
if (daCopiare.getInterCompany() != null){
nuova.setInterCompany(daCopiare.getInterCompany());
}
if (daCopiare.getArticoli() != null || daCopiare.getArticoli().size() != 0){
nuova.setArticoli(daCopiare.getArticoli());
}
}
And then in your call:
Area nuova = CopiatoreDiArea(daCopiare);
If you copy primitives (or the special primitive wrapper classes) in Java, the runtime will always do a deep copy of the values. To illustrate this, I show a few examples.
See http://jdoodle.com/a/3TL for an online runnable version of the code below:
public class MyClass {
public static void main(String[] args) {
int a = 10;
int b = a;
b = 20;
System.out.println(a + " != " + b);
// We did not change a when changing b.
Integer c = 10;
Integer d = c;
d = 20;
System.out.println(c + " != " + d);
// We did not change c when we changed d, even though they are class instances.
// This shows that primitive wrappers are handled differently due to
// autoboxing.
// See https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html
MyInteger e = new MyInteger(10);
MyInteger f = e;
f.value = 20;
System.out.println(e + " == " + f);
// Changing the data contained within f also affected e. The two variables now point to the same instance.
MyInteger g = new MyInteger(10);
MyInteger h = new MyInteger(g);
h.value = 20;
System.out.println(g + " != " + h);
// We prove that we have two instances, initially containing
// the same value but changing their internal values does not
// affect each other.
}
private static class MyInteger {
public int value;
public MyInteger(int value) {
this.value = value;
}
public MyInteger(MyInteger other) {
this.value = other.value;
}
public String toString() {
return Integer.toString(this.value);
}
}
}
From your example, it seems you might be trying to copy complex classes, even lists maybe, and these will always copy a reference only when you use simple assignment.
There are a few options that you could take, for instance the copy constructor that I use above, or alternatively rely on some form of reflection or serialization that does the hard work for you.
Apache Commons Lang has a SerializationUtils class that will run through all internal data in your classes, serialize them into byte format and then try to re-instantiate new versions of the same classes with the serialized data.
The Cloner library makes use of reflection and some special performance cases for known types such as collections and calendars, with some great debugging options.
Declare a copy constructor for deep cloning your object
public class Area {
public Area() { // constructor }
public Area(Area objectToCopy) {
setNome(objectToCopy.getNome());
setInter(objectToCopy.getInter());
setRischioInerente(objectToCopy.getRischioInerente());
setRischioResiduo(objectToCopy.getRischioResiduo());
setControlli(objectToCopy.getChecklists());
setStrategicita(objectToCopy.getStrategicita());
setRischiosita(objectToCopy.getRischiosita());
setMediaHpReato(objectToCopy.getMediaHpReato());
setProbabilitaInerente(objectToCopy.getProbabilitaInerente());
setEsposta(objectToCopy.isEsposta());
setStrumentale(objectToCopy.isStrumentale());
setCommento(objectToCopy.getCommento());
setCondivisa(objectToCopy.isCondivisa());
if (objectToCopy.getNomeCompleto() != null)
setNomeCompleto(objectToCopy.getNomeCompleto());
else
setNomeCompleto(objectToCopy.getNome());
if (objectToCopy.getInterCompany() != null)
setInterCompany(objectToCopy.getInterCompany());
if (objectToCopy.getArticoli() != null || objectToCopy.getArticoli().size() != 0)
setArticoli(objectToCopy.getArticoli());
}
}
and then do it calling
Area newArea = new Area(oldArea);
I'm trying to use a method in another class to print out result stored in a list, in that class, but i'm having trouble using a method from another class.
Here is the method i'm using in the class event, where the list is stored:
public void listParticipantResult(Participant participant) {
ArrayList<Result> results = sortResults();
for (Result result : results) {
if (result.getParticipant().getId() == participant.getId()) {
System.out.println(result);
}
}
}
And this is where i'm trying to call the method in my main program,
but the method in the class Event cannot be resolved. I'm not sure how to declare it as an object so i can use the method.
private void participantResult() {
System.out.print("Number: ");
int participantNumber = readInt();
Team team = null;
Participant participant = null;
for (Team teamFromList : teamList){
if (teamFromList.hasParticipantWithId(participantNumber)) {
participant = teamFromList.getParticipantById(participantNumber);
team = teamFromList;
}
}
if (participant == null) {
System.out.println("Participant with number " + participantNumber + " does not exist.");
return;
}
else {
event.listParticipantResult(); <- right here.
}
}
You need to create an Event object
Event event = new Event(); //Or something similar based on constructor
You need to then make sure you are passing in a Participant as your Event.listParticipantResult() requires.
listParticipantResult(Participant participant) takes one argument of type Participant. On the 3rd line from the bottom, you are not passing any arguments:
...
event.listParticipantResult();
...
Change it to:
...
event.listParticipantResult(participant);
...
Where do you declare event? You also don't pass in any argument to the listParticipantResult() call, shouldn't you be passing in a Participant object?
I have two lists of contacts, and I want to replace one with another as:
private PhoneCAdapter getContactAdapter(ArrayList<UserAgenda> phoneContacts) throws NetworkConnetionException {
List<UserAgenda> serverContacts = WithingsAPI.getInstance().getContactListByType(Common.CONTACT_LIST_TYPE_FILE,"ALL");
for(UserAgenda pc: phoneContacts){
for(UserAgenda sc : serverContacts){
if(pc.getEmails() != null){
ArrayList<String> emailsPc = new ArrayList<String>(pc.getEmails());
for(String epc: emailsPc){
ArrayList<String> emailList = new ArrayList<String>(sc.getEmails());
String emailServer = emailList.get(0);//server contact has only one email
if(epc.equals(emailServer)){//we have to substitute the object from the server with the phone ones.
pc = sc;
}
}
}
}
}
PhoneCAdapter ca = new PhoneCAdapter(this, 0, phoneContacts,PhoneContacts.this );
return ca;
}
But after the loops my variable phoneContacts still has the same values. Only if I change the fields manually as:
if(epc.equals(emailServer)){
pc.setUserOfWW(sc.getUserOfWW());
if(sc.getInvited().equals("true")){
pc.setInvited("true");
}
else{
pc.setInvited("false");//here we have people who are/arent user of WW
pc.setId2invite(sc.getId2invite());
}
}
How could I replace my object with info from the phone with the user I get from the server, without doing it manually for each field?
Changing the local variable you're using for the iterator doesn't change the content of the collection. It's very important that you understand the difference between modifying the object that a variable's value refers to, and modifying a variable. If you modify the object that the reference within a list refers to, that change will be visible via the list. If you modify a variable which basically contains a copy of that reference, that won't affect the list at all.
I suspect you want:
for (int i = 0; i < phoneContacts.size(); i++) {
UserAgenda pc = phoneContacts.get(i);
for (UserAgenda sc : serverContacts) {
if (pc.getEmails() != null) {
ArrayList<String> emailsPc = new ArrayList<String>(pc.getEmails());
for (String epc: emailsPc) {
ArrayList<String> emailList = new ArrayList<String>(sc.getEmails());
String emailServer = emailList.get(0);
if (epc.equals(emailServer)) {
pc = sc;
// Replace the value in the collection too...
phoneContacts.set(i, sc);
// Do you want to break here?
}
}
}
}
}
It's unclear why you're creating the array lists within the loop, by the way... (or why you're recreating the same list of emails on each iteration). Basically the code is very unclear at the moment, and I strongly suspect it could be simplified considerably - but it's hard to do so without knowing what you're trying to achieve.
public LeNo generate (PrintStream stream) {
prepareOperands(stream);
LeNo l = (LeNo)left;
LeNo r = (LeNo)right;
if (l instanceof NumNo && r instanceof NumNo) {
return new NumNo((Integer.getInteger(l.name()).intValue()*Integer.getInteger(r.name())));
}
if ((l instanceof NumNo && l.name().equals("0"))||(r instanceof NumNo && r.name().equals("0"))) {
return new NumNo(0); // cut of rest of code here....
Is there a way I can create a new NumNo method without having to create it when I return?
The thing is I still want to return NumNo, but without creating a new NumNo doing it.
It is just return new NumNo(0); that you don't want to create right? Because it is the same every time? If so, you can create a static instance of that object. For example,
private static final NewNo ZERO = new NewNo(0);
This is called the flyweight pattern, where you create commonly used instances once.
return NumNo.getClass();
To return a class instead of an instance.
Create an instance with java.lang.Class.newInstance()
for example:
klass = generate(stream);
object = klass.newInstance();