I have an arraylist of my custom class and for each of those I would like to each keep their own arraylist of computers. Here is my code for the class:
class Services {
public String name;
public String path;
public ArrayList<String> computers = new ArrayList<>();
public Services(String name, String path, String computer) {
this.name = name;
this.path = path;
this.computers.add(computer);
}
public String getName() {
return name;
}
public String getPath() {
return path;
}
public void addComputer(String computerName) {
this.computers.add(computerName);
}
}
In my main method I am checking my arraylist of Service for an object with the same name and if it exist then I just want to add that to the arraylist for that object.
However, this is not working and it seems I am just ending up with just one arraylist of all computers not specific to each object of Service.
Here is the section of my main method that uses this class.
stream.iterator().forEachRemaining(x -> {
try {
final boolean[] nextLine = {false};
lines(x.toAbsolutePath(), Charset.forName("UTF-16")).forEach(y -> {
if (!nextLine[0]) {
// Finding Separator
if (y.contains("-----------")) {
//Letting the program know the next line is a service.
nextLine[0] = true;
}
} else {
//Splitting the service name from the path.
String[] service = y.split(" + ");
final boolean[] exists = {false};
String computerName = x.getFileName().toString().substring(0, x.getFileName().toString().length() - 4);
allServices.iterator().forEachRemaining(z -> {
if (z.name.contains(service[0])) {
exists[0] = true;
}
});
if (!exists[0]) {
//Creating new service object if it does not exisit.
//Params are Service name, service path, computer name
Services serviceToAdd = new Services(service[0], service[1], computerName);
//Then adding it to the list to be printed out later.
allServices.add(serviceToAdd);
} else {
//Service name already exists, just adding the computer name to its list of affected computers.
allServices.iterator().forEachRemaining(z -> {
if (z.name.contains(service[0])) {
if (!z.computers.contains(computerName)) {
z.addComputer(computerName);
}
}
});
}
}
}
);
} catch (Exception ex) {
}
});
Ultimately, I am trying to compile a list of services. With that list of services I need to know the name of the service, the path, and which computers have them. I am getting the computer name from the name of the file. It appears that the list of computers for each service is the same list instead of a different list for each service. How do I fix this? Do I need to make a list of lists? That seems redundant and ill performing.
It's pretty hard to tell you what you are missing as you do not provide us the main method which is the most important one relating to your post.
So, with the few info I had, here a little algorithm that would loop over all your stored computers according to the code you posted. That should help you figure out what you are missing, else please post the main method.
public static void main(String args[]) {
String newComputer = "UberPC3000x";
boolean alreadyExistSomeWhere = false;
for (int i = 0; !alreadyExistSomeWhere && i < allMyServices.size(); i++) {
for (int j = 0; !alreadyExistSomeWhere && j < allMyServices.get(i).computers.size(); j++) {
alreadyExistSomeWhere = allMyServices.get(i).computers.get(j).equals(newComputer);
}
}
if (!alreadyExistSomeWhere) //Then it means it was not found and you are free to add wherever you want.
{
}
}
Related
I am fairly new to java and working on a project to simulate a CPU scheduler in Java and i am using a linked list to store each process object that is read in from a external master list. When I test print the processes and the variables they contain, everything comes out as expected but whenever I try and do something with them it stops working.
public class process
String ID;
int Arrive;
int ExecSize;
int Execstore;
int Tstart;
int Tend;
int quant;
public process(String ID,int Arrive,int ExecSize) {
this.ID = ID;
this.Arrive = Arrive;
this.ExecSize = ExecSize;
this.Execstore=ExecSize;
this.Tend = 0;
this.Tstart = 0;
this.quant = 4;
}
public void setquant(int update) {
this.quant = update;
}
public int getquant() {
return quant;
}
public void setExecSize(int update) {
this.ExecSize = update;
}
public void setTend(int update) {
this.Tend = update;
}
public void setTstart(int update) {
this.Tstart = update;
}
String getID() {
return ID;
}
int getArrive() {
return Arrive;
}
int getExecSize() {
return ExecSize;
}
int getTstart() {
return Tstart;
}
int getTend() {
return Tend;
}
int getExecstore() {
return Execstore;
}
and this is the class used for the simulation
public class fcfs {
int disp;
int Ttotal = 0;
int Exec;
int Turn;
int Wait;
String output;
LinkedList<process> Que = new LinkedList<process>();
LinkedList<process> Quecleared = new LinkedList<process>();
public fcfs(LinkedList<process> B,int D) {
Que.addAll(B);
disp=D;
}
public void run()
{
while (Que != null)
{
Ttotal = Ttotal + disp;
System.out.println(Que.getFirst().getExecSize());
Exec=Que.getFirst().getExecSize();
output += String.format("T%d: %s\n",Ttotal,Que.getFirst().getID());
Que.getFirst().setTstart(Ttotal);
Ttotal = Ttotal+Exec;
Que.getFirst().setTend(Ttotal);
Quecleared.add(Que.poll());
}
}
So whenever i use System.out.println I get the expected result that I read into the list. But anything else I try to do in reference to elements of the process object will not work. Any help would be greatly appreciated
while (!Que.isEmpty())
{
Ttotal = Ttotal + disp;
System.out.println(Que.peekFirst().getExecSize());
Exec=Que.peekFirst().getExecSize();
output += String.format("T%d: %s\n",Ttotal,Que.peekFirst().getID());
Que.peekFirst().setTstart(Ttotal);
Ttotal = Ttotal+Exec;
Que.peekFirst().setTend(Ttotal);
Quecleared.add(Que.pollFirst());
}
This shouldn't throw an error on Exec = Que.peekFirst().getExecSize();
That error is thrown when your container is empty.
EDIT
In your code you specified the condition Que != null. In java once an object has been instantiated it is no longer considered null even if it IS empty. Most likely what was happening here is you continued iterating through your while(Que != null) loop until you had called Que.poll() on all elements of the list.
After clearing the list you did not exit the loop because Que still was not null. Then calling getFirst() on the empty instance of a LinkedList threw an exception.
A similar situation can be seen here with null vs empty strings:
Difference between null and empty ("") Java String
EDIT 2
It also appears that your class methods for getID(), getExecSize(), etc are passing values by reference as opposed to copying their value. Thus any change you make after passing the reference from queue will alter any copies you tried to make of it.
This can be best avoided by creating a new instance of an object and returning that from your function. Shown in an answer on the question linked below:
class Foo {
private Bar myBar;
public Foo deepCopy() {
Foo newFoo = new Foo();
newFoo.myBar = myBar.clone(); //or new Bar(myBar) or myBar.deepCopy or ...
return newFoo;
}
}
For more information on ways to pass values as opposed to reference values of your pre-existing instances, as well as what a shallow copy actually is, check this link: In Java, what is a shallow copy?
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 6 years ago.
I have a snippet of code (below) that when run, will (ideally) fill an app array to look something like this:
Header 1:
App 1
App 2
Header 2:
App 3
App 4
etc.
However, when I run it in my emulator, it produces this:
Header 1:
App 1
App 2
App 3
App 4
...
Header 2:
App 1
...
I'm not sure why this happens, as I have looked up the defaults and everywhere I look, people say that Java defaults to passing by value, not by reference. If this is true, how come it adds every app to every category?
Preconditions:
Store is defined as a list of class "App", each element containing a header and title, among other things.
ListDataChild is an empty hashmap, with types > to be filled by the loop and then outputted via an expandable list view. I would post the code for the view, but it is very bulky and long so I'll just add a simple testing algorithm at the end.
EmptyList is just that, a list of type that has nothing inside (at least to begin with? Could it be changing?)
Code:
listDataChild = new HashMap<String, List<App>>();
List<App> emptylist = new ArrayList<>();
List<App> Store = synced.getAppStore();
Boolean juststarted = true;
for (App el : Store)
{
if (juststarted)
{
juststarted = false;
listDataChild.put(el.getHeader(), emptylist);
listDataChild.get(el.getHeader()).add(el);
} else {
if (listDataChild.containsKey(el.getHeader())) {
listDataChild.get(el.getHeader()).add(el);
} else {
listDataChild.put(el.getHeader(), emptylist);
listDataChild.get(el.getHeader()).add(el);
}
}
}
//TESTING
for (String header : listDataChild.keySet())
{
for (int j = 0; j < listDataChild.get(header).size(); j++)
{
System.out.println("HashMap at " + header + ", " + j + ": " + listDataChild.get(header).get(j).getTitle());
}
}
App.Java:
public class App {
public String header,title,link,url,redirect,icon;
public Double order;
public Boolean selected;
public App() {
header = "";
title = "";
link = "";
url = "";
redirect = "";
icon = "";
order = 0.0;
selected = false;
}
public int compareTo(App another) {
if (this.getOrder()<another.getOrder()){
return -1;
}else{
return 1;
}
}
public void setHeader(String h) {
header = h;
return;
}
public void setTitle(String t) {
title = t;
return;
}
public void setLink(String l) {
link = l;
return;
}
public void setUrl(String u) {
url = u;
return;
}
public void setRedirect(String r) {
redirect = r;
return;
}
public void setIcon(String i) {
icon = i;
return;
}
public void setOrder(Double o) {
order = o;
return;
}
public void setSelected(Boolean s) {
selected = s;
return;
}
public String getTitle()
{
return title;
}
public String getHeader()
{
return header;
}
public Double getOrder()
{
return order;
}
}
Thanks in advance!
Yes you are right, java does pass by values but there are tricky situations:
if you are using primitive data type: pass by value works fine.
if you use Objects instead of primitive data type: pass by value works but for address of passing object. So it looks like passing reference.
I know concept almost look like same but technically, it is pass by value.
Have a look at this link
I need some help on my class design or better said a reference to a common design pattern for a problem.
I am working in the aircraft industry. So far my programming skills are VBA and basic JAVA applications.
As an engineer my task is to create CAD Models for fixating components in and on to aircraft kitchens. To ensure a high reusability and to reduce development time I want to create a program which can recommend previous solutions.
Basically each aircraft operator can select from a catalog which galleys/kitchens (Monument) it would like to have installed. Inside these Monuments are multiple compartments. Inside a compartment we can install multiple equipment’s/components.
I would like to write a program which can tell me "you have installed these components together before -> In this compartment -> in that aircraft for that customer"
I have modeled the compartment, the monuments, and the aircraft. Each class extends form the same class BaseHolder:
public abstract class BaseHolder <I> {
private final ArrayList <I> heldItems = new ArrayList<I>();
public boolean addItem(final I i){
Objects.requireNonNull(i, "cannot add NULL");
return heldItems.add(i);
}
public boolean removeItem(I i){
return heldItems.remove(i);
}
public boolean contains(I i){
return heldItems.contains(i);
}
public int itemCount(){
return heldItems.size();
}
public boolean isEmpty(){
return heldItems.isEmpty();
}
public void Clear() {
heldItems.clear();
}
protected List<I> getHeldItems(){
return heldItems;
}
public I getElement(int n){
return heldItems.get(n);
}
}
public class Aircraft extends BaseHolder<Monument> {
// code
}
public class Monument extends BaseHolder<Compartment> {
private String name;
public Monument (String name){
this.setName(name);
}
// code
#Override
public boolean addItem(final Compartment c) {
Objects.requireNonNull(c, "cannot add NULL");
if (contains (c) ){
throw new IllegalArgumentException("Compartment already added!");
};
for(Compartment ctmp : getHeldItems()){
if (ctmp.getName().equals(c.getName() ) ) {
throw new IllegalArgumentException("Compartment with an identical name already exits");
}
}
return getHeldItems().add(c);
}
public Compartment getCompartment(int n){
return getHeldItems().get(n);
}
public Compartment getCompartment(String name){
for(Compartment ctmp : getHeldItems()){
if (ctmp.getName().equals(name) ) {
return ctmp;
}
}
return null;
}
}
public class Compartment extends BaseHolder<IWeighable>{
private String name = "";
private double MAX_LOAD = 0.0;
public Compartment (String name ,final double max_load){
this.setName(name);
updateMaxLoad(max_load);
}
// code
protected double getTotalLoad(){
// code
}
/**
*
* #param load
* #throws InvalidParameterException if max load not >= than 0.0
*/
public void setMaxLoad(final double load){
if (load >= 0.0){
this.MAX_LOAD = load;
} else {
throw new InvalidParameterException("max load must be greater than 0.0");
}
}
public boolean isOverloaded(){
return (getTotalLoad() > MAX_LOAD ) ;
}
}
The problem I am having is that this design seems to have many flaws. Apart from it being rather tedious: getElement(n).getElement(n).getElement(n)
Adding elements to a compartment results in all aircrafts using the same compartment, having all the same equipment’s/components installed. As it is the same object in the DB. An instance of the compartment would be need. Cloning the DB Compartment before adding it to an aircraft is no option. I need to be able to change the allowable loads, a change it for all. To resolve this I thought of using some type of “wrapper” class as in:
public class MonumentManager {
public ArrayList <Monument> monuments = new ArrayList<>();
public ArrayList <LinkObect> links;
class LinkObect{
private Compartment c;
private IWeighable e;
LinkObect(Compartment c, IWeighable e){
this.c = c;
this.e = e;
}
}
public boolean addMonument(Monument m){
return monuments.add(m);
}
public void addElementToCompartment(IWeighable e, Compartment c){
boolean known = false; //to check if the passed compartment is known/handeld to/by the MonumentManager
for (Monument m : monuments){
if ( m.getCompartment(c.getName() ) != null ) known = true;
}
if (known){
links.add(new LinkObect(c, e));
} else {
throw new IllegalArgumentException("Compartment is not inside a managed Monument!");
}
}
public List<Compartment> whereUsed(IWeighable e){
// TODO
}
}
This class might solve the problem but it is feels odd. Can anybody point me in the right direction towards a common design pattern etc. I am reading a book from the local library on design patterns. But it seems to be slightly above me. (as is maybe my task).
Any suggestions / help etc would be highly appreciated.
I hope I'm understanding this correctly.
One thing is the Component you want to install that has certain characteristics and another thing is some representation of what you have installed.
The information of your installation does not need to be in your Component but in something else, let's call it Installation.
Your Installation has to know 2 things:
What kind of Component it is.
What other Installations it has inside.
The installation will look something like this.
public class Installation {
private Component type;
private List<Installation> content;
public Installation(Component type){
this.type = type;
this.content = new ArrayList<Component>();
}
//you can have methods for add, remove, etc...
}
Feel free to ask further clarifications.
I've got a method called removeSup which is supposed to remove an object Supplement from a list of supplements.
this is the code for the method:
private static void removeSup(Supplement supToRemove, List<Supplement> listToRemoveFrom) {
Iterator<Supplement> iterator = listToRemoveFrom.iterator();
while(iterator.hasNext()){
if(iterator.next().equals(supToRemove)){
iterator.remove();
}
}
}
there is a class called magazine which defines the list of supplements.
public class Magazine {
private List<Supplement> supList;
public List<Supplement> getSupList() {
return this.supList;
}
public void setSupList(List<Supplement> supList) {
this.supList = supList;
}
public Magazine(Double cost, String _name){
this.supList = new ArrayList<>();
this.weekCost = cost;
this.name = _name;
}
}
the class supplement has the following constructor
public Supplement(String _name, Double _price, String _magName ){
this.name=_name;
this.price=_price;
this.magName = _magName;
}
in the main class client there is a search that the user can do to remove a certain Supplement
private static void searchSup(){
System.out.println("Search for Supplement");
String search = scanner.nextLine();
for (Supplement sup : magazine.getSupList()) {
if (!sup.getSupName().equalsIgnoreCase(search)) {
//do something
}
else{
removeSup(sup,magazine.getSupList());
}
}
}
the main method in the client class is as follows:
private Magazine magazine;
public static void main(String[] args) {
magazine = new Magazine(3.0, "pop");
List<Supplement> startList = new ArrayList<>();
startList.add(new Supplement("Nat Geo", 3.0,"pop"));
startList.add(new Supplement("Discovery", 5.0,"pop"));
startList.add(new Supplement("Health", 6.3,"pop"));
startList.add(new Supplement("IT", 8.3,"pop"));
magazine.setSupList(startList);
searchSup();
}
When I run this program and type any of the added supplements, i get an error
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
at java.util.ArrayList$Itr.next(ArrayList.java:831)
at Client.searchSup(Client.java:131)
at Client.searchSup(Client.java:140)
at Client.main(Client.java:588)
is it the for loop i am using to search giving me an error? if so how would i go about fixing this?
You generally shouldn't modify a Collection while iterating over it. It's fine to modify elements, but you really shouldn't remove something from a Collection while iterating. See here: http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html. Also, the Javadoc for ConcurrentModificationException may be helpful.
You might try returning a new list with the Supplement removed:
private static List<Supplement> removeSup(Supplement supToRemove, List<Supplement> listToRemoveFrom) {
List<Supplement> filteredSupplements = new ArrayList<Supplement>();
for(Supplement supplement : listToRemoveFrom) {
if(!suppplement.equals(supToRemove)){
filteredSupplements.add(supplement);
}
}
return filteredSupplements;
}
It seams that the "magazine" is local var in the method of main, not accessible to searchSup.Fix it like
private void searchSup(Magazine magazine)
{
//...
}
and more details if you can provide, the codes in Line 131 and 140 will be helpful.
I figured out that the search i was doing was not working with what i wanted to do so i created a method which returns an integer of the Supplement in the list.
private static int indexOfSup(List<Supplement> supSearchList, String nameOfSup) {
for (Supplement sup : supSearchList) {
if (sup.getSupName().equalsIgnoreCase(nameOfSup)) {
return supSearchList.indexOf(sup);
}
}
return -1;
}
i then use this integer to remove from the list.
a simple List.Remove(index) worked fine
Thanks for all the replies.
Basically, i have a class where i have my arrays in, which is like this
public final class DepotDatabase {
private Driver[] arrayDrivers;
public DepotDatabase() {
arrayDrivers = new Driver[4];
arrayDrivers[0] = new Driver(1234, 1234, 0); // sample driver
arrayDrivers[1] = new Driver(4444, 4444, 0); // sample driver
arrayDrivers[2] = new Driver(1337, 1337, 1); // sample manager
arrayDrivers[3] = new Driver(1234, 1234, 0); // sample driver
}
and i want to print this array in another class, i did set up the array in another class
public Driver(int username, int password, int managerCheck) {
this.username = username;
this.password = password;
this.managerCheck = managerCheck;
}
but now i want to be able to print out all the drivers, but in another class which will be called ViewDrivers or something similar
You can create a method inside DepotDatabase to print the array, then create an object from and call print method.
public final class DepotDatabase {
private Driver[] arrayDrivers;
public void printArray() {
for (int i = 0; i < arrayDrivers.length; i++) {
Driver d = arrayDrivers[i];
System.out.println("Username : " + d.getUsername());
System.out.println("Password : " + d.getPassword());
System.out.println(" Manager Check: " + d.getManagerCheck());
}
}
the from the test class you can do:
public void execute() {
DepotDatabase ddb = new DepotDatabase();
ddb.printArray();
}
That's why you'll need to have getters and setters. You should have:
public Driver[] getDrivers() {
return arrayDrivers;
}
and in the other class, you simply call it (and print it or whatever).
Read this tutorial.
If you plan to print your array in another class you show create an accessor to it.
The common pattern for Java is to use "get plus name off attribute", getDrivers() you should also avoid the class name in such geter as it may changed due to application life.
public final class DepotDatabase {
//your code
public Driver[] getDrivers() {
return this.arrayDrivers;
}
}
Next question to answer is a returning the whole array is good idea. When you return it as above you loose control on it. And every one that call that method will be able to change the content of it.
To prevent this you should use so called Defensive copying
public Driver[] getDrivers() {
return Arrays.copyOf(arrayDrivers, arrayDrivers.length);
}
Then person will get an copy of it an will not harm your class.
The issue with this is that consumer of your class will have to call this method every time to get fresh list of cars.
To solve this issue you may want to user the [collection framework] where instead of array you cold define:
List<Driver> drivers new ArrayList<>();
and provide the drivers as [immutable] list
public Iterable<Driver> getDrivers() {
return java.util.Collections.unmodifiableList(drivers);
}
Iterable is an interface, that allow you to obtain an interator the the list consumer of class wold have possibility to traverse it. IF you wan to allow him to check that list contains some driver you can set the return type as Collection
class Storage {
private String items[] = new String[10];
public String[] getItems() {
return Arrays.copyOf(items, items.length);
}
}
class Store {
Storage storage = new Storage();
private void printStorage() {
String[] items = storage.getItems();
for (String item : items) {
}
}
}