This isn't a question that I am expecting a specific answer to since it is pretty broad. I'm teaching myself Java and am focusing specifically on dynamic memory allocation. Let's make a very oversimplified example: Say that I have a really basic data entry screen. So basic that all that happens is the user enters a series of first names, maybe for an employee directory or something. On my JFrame, I have a single JTextField control where these names are entered. The number of employees is known only at run time. The user enters a name and hits the enter key, which commits the name to memory and creates a new object to store the next name (silly, I know, but I'm trying to focus). Something like this (don't take this too literally - I obviously didn't compile this):
public class Employee {
String fName;
public void setName( String n ) {
fName = n;
}
};
public class JFrameEmp {
//blah, blah, blah
JTxtName.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
/* Handle the enter key */
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
/* Store name */
this.setName(JTxtName.getText());
/* Create New Object */
Employee next = new Employee();
}
};
}
}
Where I need help is on the last line. Even if this were to work, let's say that I wanted to print out a list of the names entered. In my approach, I see no way to uniquely identify each object (so that I can iterate through them).
Do I need to create an array to store these? But that has a fixed length and lives on the stack. I'd rather find a way to use the heap to allow for an open-ended list.
What should I be reading to learn how to do this? It must be a very common thing to do, but the books that I have don't seem to cover it.
Thanks. I hope that I have explained this well enough without going into too much detail.
It sounds like you want to store a List of Employees. Java provides dynamically sized array with its ArrayList class.
Here is an example:
ArrayList<Employee> employees = new ArrayList<Employee>();
employees.add(new Employee("Alice"));
employees.add(new Employee("Bob"));
System.out.println(employees.get(0)); // prints out Alice
You could use an array. You might find it useful to have a look at the Java Collections framework, in particular the page about the implementations.
But yes you will need to be adding the objects to some sort of data structure otherwise they will be getting cleaned up by the garbage collector after there is no valid reference to them.
It seems like you are looking for a data storage structure.
You could use a built in array, which is actually stored on the heap in java(the only issue is that you would have to keep track of size and reallocate when more space is needed).
A better option would be an ArrayList, which has built in add methods that automatically resize when needed.
You could also use a HashMap, which would allow to quickly search for your employees by name.
Related
I'm building some kind of game for programming class and I need to have a history of the people who played, you can play multiple times when you run the game, so I'm not trying to store it permanently just when the game is executing.
I was thinking maybe some kind of array or something that can store all the string variables (names), but I don't how to do this indefinitely until the game stops.
Also, I am not allowed use java data structures (ArrayList, LinkedList, etc.)
.
Alternatively, if this is not possible or very complicated, maybe some way to store the names of only the last 10 people that play would work.
Any help is appreciated.
If data structures are not allowed, you could actually just make do of a comma-delimited String because an array in order to initialize you need to specify its size already (but this is something you definitely cannot know yet). Have a static instance of the String, then append to it a delimiter (comma) and the the player name.
private static String commaDelimitedStr = "";
public void addPlayerName (String playerName) {
commaDelimitedStr = commaDelimitedStr.concat(",").concat(playerName);
}
Then at the end you can split the String to get an array version of it.
String[] names = commaDelimitedStr.split(",");
I have an object Person with the following fields:
firstName, secondName, age, nationallity, address, phoneNr.
And the list: ['John', 'Smith', '35', 'american', 'San Francisco', '+0324 235 327'].
I would like to put the values of the list into the object Person, without using the classic method of setting each value.
I want to avoid this:
person.setFirstName(list.get(0));
person.setSecondName(list.get(1));
person.setAge(list.get(2));
person.setNationallity(list.get(3));
person.setAddress(list.get(4));
person.setPhoneNumber(list.get(5));
My object has more fields than the ones I've put here as example (about 15), and I want to avoid writting a lot of code.
So my question is there a more elegant way of dumping all the values from the list into the object? I was thinking that in Java 8 maybe is there something but so far I haven't found anything.
There is no way to dump all values from the list into object, but you can add a new contructor in your Person Class, with a list as parameter like this :
public Person(List<String> list) {
this.firstName(list.get(0));
this.secondName(list.get(1));
this.age(list.get(2));
this.nationallity(list.get(3));
this.address(list.get(4));
this.phoneNumber(list.get(5));
}
and the call will be like :
Person person = new Person(list);
The other answer is good, there is one trick that can make it easier to work with though. This is especially relevant if there are a large number of entries such as the 15 mentioned in the question:
public Person(List<String> list) {
int index = 0;
this.firstName(index++);
this.secondName(index++);
this.age(index++);
this.nationallity(index++);
this.address(index++);
this.phoneNumber(index++);
}
Now you can add things to the list in any position or change the order or otherwise adjust it and don't have to manually update all the indexes. It also removes the risk of human error in accidentally getting an index wrong - although you do still need to get all the fields in the right order.
Noob Java question here. I am wondering if there is a standard way to add additional/external properties to a POJO. i.e., say I have a User Object that I add to an ArrayList in my program. This Object will contain things like first name, last name, address, email, phone, etc., corresponding to whatever is defined in my database.
Now say that I have the requirement to include external attributes along with said User, such as Employer ID, Vehicle Plate #, Smartphone type. I will need to be able to include these extra properties when adding a User to my ArrayList - Is it possible to attach these strictly with Java so that I can have acces to them?
I've thought of going with something like a Value Object, in where the VO would include all the User Properties along with the extra fields to be added from outside Classes, but want to explore more possibilities. Any ideas? Thanks much
You have many possibilities. Here are a few that immediately spring to mind:
Refactor the User class. This is the obvious one, so I presume you have a good reason for not doing so.
Write a class that extends User, containing this information. Presuming you're only storing this information for a subset of the users that this information applies to, this makes the most sense.
Use composition - create a new class that holds a user instance and then any other information you want to add to it.
One big influence on what design you use will be whether all additional values are unique, or if a User can have multiple smartphones, vehicles, etc.
If all additional fields are all unique you can just slide in java.util.Properties (or other Maps). Your User class needs at least
import java.util.Properties;
class User
{
Properties extra_attr = new Properties();
// ... existing code ...
public void setExtraAttr(String field, String value) {
extra_attr.setProperty(field,value);
}
public String getExtraAttr(String field) {
return extra_attr.getProperty(field);
}
}
Then use calls like some_user.setExtraAttr("Employer ID","314159"); and some_user.getExtraAttr("Employer ID"); to set and get your extra attributes.
If you need multiplicity you may need a different approach, or you can just code over your implementation of Properties. For instance, you can rewrite setExtraAttr() to look for existing keys and add an index
public void setExtraAttr(String field, String value) {
if(extra_attr.getProperty(field) == null)
extra_attr.setProperty(field,value);
else {
int index = 1;
while(extra_attr.getProperty(field+index) != null)
index++;
extra_attr.setProperty(field+index,value);
}
}
You then need some kind of loop where ever you get attributes to look for and handle the multiple extra records.
i am going to type my code here and then I will explain my problem below.
for (int i = 0; i < sales.totalSales(); i++) {
EntidadGeo gec = sales.getSale(i).getCustomer();
EntidadGeo get = sales.getSale(i).getStore();
int[] c = geo.georeferenciar(sales.getSale(i).getCustomer().getCP(), ventas.getVenta(i).getCCustomer().getCalle(), ventas.getVenta(i).getCCustomer().getProvincia());
gec.setX(c[0]);
gec.setY(c[1]);
int[] c2 = geo.georeferenciar(ventas.getSale(i).getStore().getCP(), ventas.getVenta(i).getStore().getCalle(), ventas.getSale(i).getStore().getProvincia());
get.setX(c2[0]);
get.setY(c2[1]);
mapaventas.representar(gec, get);
}
I have that for loop, what i want to do in my project is to print in a map. The point is what I need to draw in the map are customers and stores and one store can sell to many customers at the same time. In my project I am using MVC pattern, this part belongs to Controller part, and in the model part i draw the map.
It works now but the problem is that my project draw one customer and one store instead of 4 customers per 1 store.
Thanks
Your problem is here:
mapaventas.representar(gec, get);
So it looks like you have a Map<Vendor, Client> which will only associate only one client per vendor. I have to guess at this because we have no knowledge what the method above does. If I am correct a better solution perhaps is to use a Map<Vendor, ArrayList<Client>>. so that a Vendor can be associated with multiple clients. Then you would do something like
ArrayList<Client> getList = mapaventas.get(gec);
// if the above is null, create the arraylist first and put it
// and the gec into the map.
getList.add(get);
Note that my variable names and types will not be the same as yours, but hopefully you will understand the concept I'm trying to get across. If not, please ask.
It sounds like your database has a one-to-many relation between Store and Customer. A corresponding object model might be List<Map<Store, List<Customer>>>. Because a Customer may trade at more than one Store, you want "to check there if there is an IdStore already drawn, and then I don't want to draw it."
One approach would be to iterate through the List and add entries to a Set<Location>. Because implementations of Set reject duplicate elements, only one copy would be present, and no explicit check would be required. As a concrete example using JMapViewer, you would add a MapMarker to the mapViewer for each Location in the Set, as shown here.
Maybe there is a method that does this that I don't know about - I doubt it though - but I'm trying to convert an array of strings to an array of Objects. Here is the problem: I'm reading a file in from the command line. The file represents several classes of the following types each with their own data fields. Vehicle is the parent class of all who follow: Vehicle,Car,American Car, Foreign car, Truck, Bicycle.
I have no problem reading the file into a string array. However I need to create objects of all these types and store them in an array of type Vehicle[]. For example a portion of the file looks like this:
Vehicle
Kim Stanley Robinson
2344 court drive
(221)885-7777
stackoverflow#overflow.com
American Car
John Bunyon
1010 binary lane
(221)885-55643
bgt.com
convertable
made in detroit
union plant
Where Class type is the first line followed by, Owner's Name, address, phone number, email address...Each type has fields particular to it. So a foreign car is not made in Detroit. Each of these fields appear on a separate line in the file. So what I've done is read the entire file into a string array. However, I need to find my types in the array of strings,create objects of those types, and store them in a Vehicle array. My main problem is that each data field is on a separate line. How should I approach this problem?
This is java code by the way.
Initially reading the data into a String array is fine. Then you need to loop through that array, and based on the "first line" of each loop ("Vehicle", "American car" etc) you will know how many subsequent elements of the array belong to the same.
Something like this (i'll let you fill in the blanks yourself):
int i = 0;
ArrayList<vehicle> vehicles = new ArrayList();
while (i < data.length)
{
if (data[i].equalsIgnoreCase("vehicle"))
{
Vehicle vehicle = new Vehicle();
vehicle.setOwner(data[++i]);
...
vehicles.add(vehicle);
}
else if (data[i].equalsIgnoreCase("american car"))
{
...
}
i++;
}
question is unclear. Do you want to know how to parse the file and use the words on each line to create a object of it?
pseudo:
Vehicle_ptr myVeh = null;
for each line in file
switch line
{
case vehicle: myVeh = new Vehicle();
case American Car : myVeh = new AmericanCar();
default:
if (line.startswithaninteger && (myVeh != NULL)) myVeh.address = line;
etcetc.
}
Tips: use typeidentifiers in the textfile.for example:
car:americancar
address:12345 bla
etcetc
Or use a serializer
You could read the file as you are doing just now but when you read a string that is a Class type create an instance of the correct Vehicle type. It would appear that you would then know that the next x lines of the file are properties of that particular type so you would read the properties and set them on your Vehicle instance. You then have your Vehicle instance to add to the Vehicle array.
I would use a Factory pattern that creates Adapters. The factory would take the string (Vehicle, American Car) and the adapter would take the string array and current index. The adapter would be responsible to knowing how many indices to read and return the concrete object (or an interface).
IAdapter adapter = AdapterFactory.Create( "American Car" );
Object concreteObject = adapter.Popluate( stringArray, currentIndex );
Now, if you have control over how the data is stored, you might want to look into standard serialization, even JSON, to make processing easier.
It seems to me you need a factory pattern to build your set of vehicle types from the inputs. The factory can look after determining where one car specification starts and another one ends. It'll then determine the set of fields for a car, and determine the car type. It can then call the appropriate constructor, passing in all the related fields.
This means that a constructor of (say) an American car specifies all the fields that it's interested in. A European car constructor would do the same. Each constructor can assert on what it's been given so you don't create any cars incorrectly.
The factory will look after parsing and separating the inputs, and determining what is to be built. Each type of car's constructor looks after info for that car only, and performs the appropriate asserts.
The factory will maintain the list of cars created, and return that list (of America/European/Japanese) upon completion.
In pseudo-code:
whilst(!done) {
fields.add(fieldFromFile);
if (carSpecificationCompleted) {
type = getType(fields);
if (type == 'American') {
car = new AmericanCar(fields);
}
else if (type == 'European') {
car = new EuropeanCar(fields);
}
cars.add(car);
clearStoredFields();
}
}
Do you have control of the file being passed in? If so, might I suggest formatting it using XML and then parsing it using JDOM? It would make your life easier in terms of parsing. For example, you could format all vehicle entries like this:
<node type="vehicle>
<attributes location="detroit" color="red" />
</node>
Or whatever format you come up with. The benefit of this is you can then read in only the vehicles (or whatever you want), or use XPath or some other technology to efficiently get the info you want/need and load it to the proper datatype.
Disregard this advice if you have no control over file formatting.
When you have the choice, change your file format.
You can serialize your object by using xstream. Then you only have to store the complete Java object without checking if some value is existing.
I'd use the Builder pattern here instead of Factory. No big difference but find it a bit easier when the parameters vary like it seems to do in his example.