Add many element into list without instantiate too many object - java

I have a for loop like and an ArrayList as follow:
List<VehicleImpl> vehicles = new ArrayList<VehicleImpl>();
for(int i = 0; i < input.getNoVehicles(); i++) {
//Name vehicle by index
VehicleImpl vehicle = VehicleImpl.Builder.newInstance("vehicle " + String.valueOf(i+1))
//The first location - depot location is indexed as 0 in Matrices
.setStartLocation(Location.newInstance(i))
.setBreak(lunch)
.setLatestArrival(input.getOperating())
.setType(type)
.build();
vehicles.add(vehicle);
}
So, I want to ask: Is there any way I instantiate the VehicleImpl outside the loop and use the ONLY ONE instance. For each iteration, I modify the instance add the new version of instance to the list.

Yes but you have to clone the first intance at leat (By using BeanUtils for example).
Then you just update the startLocation attribute.

You could instantiate the builder outside the loop, which would halve the number of objects you're creating, but only if you were to change the builder's constructor to have zero arguments, moving the vehicle name into a setter. For example:
List<VehicleImpl> vehicles = new ArrayList<VehicleImpl>();
VehicleImpl.Builder builder = VehicleImpl.Builder.newInstance();
for(int i = 0; i < input.getNoVehicles(); i++) {
VehicleImpl vehicle = builder
//Name vehicle by index
.setName("vehicle " + String.valueOf(i+1))
//The first location - depot location is indexed as 0 in Matrices
.setStartLocation(Location.newInstance(i))
.setBreak(lunch)
.setLatestArrival(input.getOperating())
.setType(type)
.build();
vehicles.add(vehicle);
}
This is somewhat more error prone because values in the builder are not reset on each new iteration. That's not necessarily a problem for you right now, but if you were to add conditional logic, you'd probably start having a lot of problems. However, if your goal is to reduce the number of objects created, this will satisfy that.

Related

Memory leak when use newInsance() method

I have the following method with the for loops. I'm concern about the memory leaking by doing that.
My question: For every loop in for loops, Is that true that newInstance() method will allocate new memory block? If that so, should I create a VehicleImpl Instance before step into the for loop and try to set new values for this VehicleImpl Instance.
private List<VehicleImpl> setVehicles(JsonInput input) {
List<VehicleImpl> vehicles = new ArrayList<VehicleImpl>();
Break lunch = Break.Builder.newInstance("Lunch")
//timewindow(start time, end time), so lunch timewindow(start, start + duration)
.setTimeWindow(TimeWindow.newInstance(input.getLunch().getStart(),
input.getLunch().getStart() + input.getLunch().getDuration()))
//Lunch has highest priority
.setPriority(1)
//Lunch takes serviceTime
.setServiceTime(input.getLunch().getDuration())
.build();
VehicleType type = VehicleTypeImpl.Builder.newInstance("vehicleType")
.setCostPerDistance(input.getCosts().getCostPerMeter())
.setCostPerTransportTime(input.getCosts().getCostPerTransportSecond())
.setCostPerServiceTime(input.getCosts().getCostPerServiceTime())
.build();
for(int i = 0; i < input.getNoVehicles(); i++) {
//Name vehicle by index
VehicleImpl vehicle = VehicleImpl.Builder.newInstance("vehicle " + String.valueOf(i+1))
//The first location - depot location is indexed as 0 in Matrices
.setStartLocation(Location.newInstance(i))
.setBreak(lunch)
.setLatestArrival(input.getOperating())
.setType(type)
.build();
vehicles.add(vehicle);
}
return vehicles;
}
There is no leaking memory here. There is just a temporary reference variable that is created and destroyed in each iteration of the for loop. You can avoid that by declaring that variable before the for loop.

Creating multiple objects using a for loop

I'm having difficulty in creating multiple objects in a for loop the object keeps being overwritten each time the loop is run.
for(i = 0 ; i < 10; i++){
Driver one = new Driver();
}
How do I make it so that new objects are created every time the loop is run, currently one just keeps being overwritten.
Sorry for the basic question i'm just new to programming.
You can do this using array:
int n = 10;
Driver[] driverArray = new Driver[n];
for(int i = 0 ; i < n; i++){
driverArray[i]= new Driver();
}
In your code, you are declaring a local reference to Driver class, and creating new Driver object in every iteration.
It doesn't work for two reasons:
1. You are declaring local reference in for-loop so the only place, when you can use it is this for-loop.
2. Even if you declare the reference outside the loop you would initialize it with new Driver object so after loop you would have the only one Driver insance - the last one.
For more about arrays you can read here.
Hope it helps.

Assigning New Object to a Generic Array Index

I'm POSITIVE that my title for this topic is not appropriate. Let me explain. The purpose of this is to duplicate a "Profile" application, where I have a profile and so would you. We both have our own followers and in this example, we both follow each other. What this method is needed to return is a cross reference based on whom you follow that I do not. I need this method to return to me a recommended Profile object that I do not already have in my array. Right now I'm having a difficult time with one line of code within a particular method.
One of my classes is a Set class that implements a SetInterface (provided by my professor) and also my Profile class that implements a ProfileInterface which was also provided. In my code for the Profile class, I have the following object: private Set<ProfileInterface> followBag = new Set<ProfileInterface>(); which utilizes the Array bag methods from my Set class with the ProfileInterface methods I've made.
Here is the method (not complete but can't move further without my problem being explained):
public ProfileInterface recommend(){
Set<ProfileInterface> recommended;
ProfileInterface thisProfile = new Profile();
for(int index = 0; index < followBag.getCurrentSize(); index++){
Set<ProfileInterface> follows = followBag[index].toArray();
for(int followedFollowers = 0; followedFollowers < follows.getCurrentSize(); followedFollowers++) {
if()
//if Profile's do not match, set recommended == the Profile
}
}
return recommended;
}
The purpose of this method is to parse through an array (Profile as this example) and then take each of those sub-Profiles and do a similar action. The reason for this much like "Twitter", "Facebook", or "LinkedIn"; where each Profile has followers. This method is meant to look through the highest Profiles follows and see if those subProfiles have any followers that aren't being followed by the highest one. This method is then meant to return that Profile as a recommended one to be followed. This is my first dealing with Array Bag data structures, as well as with generics. Through "IntelliJ", I'm receiving errors with the line Set<ProfileInterface> follows = followBag[index].toArray();. Let me explain the reason for this line. What I'm trying to do is take "my" profile (in this example), and see who I'm following. For each followed profile (or followBag[index]) I wish to see if followBag[index][index] == followBag[index] and continue to parse the array to see if it matches. But, due to my confusion with generics and array bag data structures, I'm having major difficulties figuring this out.
I'd like to do the following:
//for all of my followers
//look at a particular followed profile
//look at all of that profile's followers
//if they match one of my followers, do nothing
//else
//if they don't match, recommend that profile
//return that profile or null
My problem is that I do not know how to appropriately create an object of a Profile type that will allow me to return this object
(in my method above, the line Set<ProfileInterface> follows = followBag[index].toArray();)
I'm trying to make an index of my Profile set to an object that can later be compared where my difficulties are. I'd really appreciate any insight into how this should be done.
Much appreciated for all help and Cheers!
When you do:
Set<ProfileInterface> follows = followBag[index].toArray();
you're trying to use Set as Array. But you can't.
Java will not allow, because Set and Array are different classes, and Set does not support [] syntax.
That is why you get error. For usefollowBag as Array you have to convert it:
ProfileInterface[] profileArray = followBag.toArray(new ProfileInterface[followBag.size()]);
for(int i=0; i<profileArray.length; i++){
ProfileInterface profile = profileArray[i];
//do what you would like to do with array item
}
I believe, in your case, you don't need assign Set object to generic Array at all. Because you can enumerate Set as is.
public class Profile {
private Set<ProfileInterface> followBag = new HashSet<Profile>();
...
public Set<ProfileInterface> recommended(){
Set<ProfileInterface> recommendSet = new HashSet<ProfileInterface>();
for(Profile follower : followBag){
for(Profile subfollower : follower.followBag){
if(!this.followBag.contains(subfollower)){
recommendSet.add(subfollower);
}
}
}
return recommendSet;
}
}
I also added possibility of returning list of recommended profiles, because there is may be several.

Java for loop and nested if statement

I have trouble to figure out where is the problem in my code. I have an employee array list, and assignment array list. The goal is to add to availableEmpAry only those employees whose skill array contains all required skills and is available on the time of shift.
The problem is after I have found employee with required skills. When starting the second loop, it does not check if an employee is available on that time. It always jumps to the else and displays the message box.
for (int j = 0; j < empAry.size(); j++){
//Checking if employee skill array has an exact skill for cs
if (empAry.get(j).empSkillAry.containsAll(tempShift.Schedule.skillRequiredAry)){
for(int i = 0; i < assignmentAry.size(); i++){
if(assignmentAry.get(i).employee.equals(empAry.get(j))){
Date shiftStart= tempShift.Start;
Date shiftEnd=tempShift.End;
Date empAsStart=assignmentAry.get(i).Start;
Date empAsEnd=assignmentAry.get(i).End;
if(empAsStart.before(shiftEnd) && empAsEnd.after(shiftStart)){
JOptionPane.showMessageDialog(availableEmp, "No Available Employee!");
}else{
availableEmpAry.add(empAry.get(j));
availableEmp.setModel(
new DefaultComboBoxModel<Object>(availableEmpAry.toArray())
);
}
}else{
availableEmpAry.add(empAry.get(j));
availableEmp.setModel(
new DefaultComboBoxModel<Object>( availableEmpAry.toArray())
);
}
}//closing assignment loop
}else{
JOptionPane.showMessageDialog(availableEmp, "No employee with required skill!");
}
} // closing loop for employee
At the start of the second loop there is the following line of code:
if(assignmentAry.get(i).employee.equals(empAry.get(j)))..
It is not clear what type of object is employee, but in order for this condition to be TRUE and to enter the block where you check the availability,you need to properly implement the equals method for the JAva class associated with the employee objects.
It is also recommended that the type of assignmentAry.get(i).employee and the type of empAry.get(j) should be the same in order for the equals method to make sense. This is not a JAVA constraint but more like a design constraint.

Get the array from an AtomicLongArray

Using Java 1.6 and the AtomicLongArray, I'd like to "copy" the original AtomicLongArray into a new one. There is a constructor that takes an array (AtomicLongArray(long[])), so I thought I could just get the array from the original one and give it to the constructor.
Sadly, the actual long[] in the AtomicLongArray is private and there seem to be no getters for it. Is there any way to do this, meaning copy the values from one AtomicLongArray to another? I can't create my own class based on this class, as the sun.misc.Unsafe class is not available to me.
This is needed because I'm going to iterate over the values, and I don't want them modified by another thread during iteration. So I thought I could make a copy and use that for the iteration...
Thanks!
Phillip
I suspect you have to create your own long[] and populate it first, or just iterate over the original:
AtomicLongArray copy = new AtomicLongArray(original.length());
for (int i = 0; i < copy.length(); i++)
{
copy.set(i, original.get(i));
}
Note that although each individual operation in AtomicLongArray is atomic, there are no bulk operations - so there's no way of getting a "snapshot" of the whole array at time T. If you want that sort of behaviour, I believe you'll need to use synchronization.
This data structure allows concurrent updates to individual entries in the collection. There is not overall lock, so you can't prevent another thread changing the contents while you are iterating over it.
If you need this, you need a workaround, e.g. copy the array and loop again to check it hasn't changed. If changed, repeat. Or you need a collection which supports a global lock.
long[] copy = new long[original.length()];
boolean changed = true;
// repeat until we get an unchanged copy.
while(true) {
for (int i = 0; i < copy.length(); i++) {
long l = original.get(i);
changed |= copy[i] != l;
copy[i] = l;
}
if (!changed) break;
changed = false;
}
This is not completely safe, but may be enough for what you need.

Categories