I don't think i have the terminology correct, haven't been one for that. What i'm trying to do is get a string back , then use it to run functions. .. Example :
int slotNumber = ((j*3)+i+1);
String slotString = "slot"+slotNumber;
Regularly I can do this :
slot12.Draw();
And I want to be able to do this :
slotString.Draw();
With it substituting slotString with slot12 in a dynamic scenario. If i truly have to i could do something similar to :
if (slotString == slot1) slot1.Draw();
if (slotString == slot2) slot2.Draw();
And such, but i dont really want to use x number of lines for x number of slots.
Any help is appreciated :D
A possible solution would be to use a HashMap where the key is the slotNumber and the value points to the slot. Then you could do something like the following.
//Initialize at the start of your program
HashMap<int, Slot> SlotHash = new HashMap<int, Slot>();
//Code to retrieve slot and call Draw().
Slot select = SlotHash.get(slotNumber);
select.Draw();
Maybe use a Map if your slots are sparsely-packed. If they're densely-packed, you might be able to use an array of slots. In either case, you do the slot lookup based on index and then call Draw on the looked-up slot.
You would have something like this:
Slot slot1 = new Slot("slot1");
Slot slot2 = new Slot("slot2");
SlotController controller = new SlotController();
controller.add(slot1);controller.add(slot2);
String someSlotNumber = ".....";
controller.draw(someSlotNumber);
See the definition of the classes below:
class SlotController {
Map<String, Slot> slotMap = new HashMap<String, Slot>();
public void addSlot(Slot aSlot) {
slotMap.put(aSlot.getSlotName(), aSlot);
}
public void draw(String slotName) {
slotMap.get(slotName).draw();
}
}
class Slot {
private String slotName;
public Slot(String name){
slotName = name;
}
public String getSlotName() {
return slotName;
}
public void draw() {
}
}
Related
I am writing test method like setTask(Task task). And Task object has several fields, e.g.
public String vehicle;
Method setTask should be used in different test-cases, so I'd like to have an options for this field to accept values:
null - the method should not do anything in this particulare case;
some string value - e.g. "", "Hello, World!", "Iso Isetta", ...
random - a value that indicates (as well as null indicates "no changes") that a random value should be selected for a drop-down list corresponding to this field.
So what can I do to make String to be SpecialString which could accept values null, random & some string value? (BTW: I don't want to set it to string value "RANDOM", and chech whether the value is equal to "RANDOM"-string)
UPDATE: I don't mean random like random value from a set of values, I mean random as well as null and this is for setTask() to handle random (select random from drop-down), and not to pass a random string from a set of values.
Pseudocode:
Task task = new Task();
task.vehicle = random; // as well as null
setTask(task)
in setTask(Task task):
if (task.vehicle == null) {
//skip
} else if (task.vehicle == random) {
// get possible values from drop-down list
// select one of them
} else {
// select value from drop-down list which is equal to task.vehicle
}
Don't assign a fixed String but use a Supplier<String> which can generate a String dynamically:
public Supplier<String> vehicleSupplier;
This, you can assign a generator function as you request:
static Supplier<String> nullSupplier () { return () -> null; }
static Supplier<String> fixedValueSupplier (String value) { return () -> value; }
static Supplier<String> randomSupplier (String... values) {
int index = ThreadLocalRandom.current().nextInt(values.length) -1;
return index > 0 && index < values.length ? values[index] : null;
}
In use, this looks like:
task.setVehicleSupplier(nullSupplier()); // or
task.setVehicleSupplier(fixedValueSupplier("value")); // or
task.setVehicleSupplier(randomSupplier("", "Hello, World!", "Iso Isetta"));
and you can get the String by
String value = task.vehicleSupplier().get();
or hide the implementation in a getter function
class Task {
// ...
private Supplier<String> vehicleSupplier;
public void setVehicleSupplier(Supplier<String> s) {
vehicleSupplier = s;
}
public String getVehicle() {
return vehicleSupplier != null ? vehicleSupplier.get() : null;
}
// ...
}
What you may want to do is to create an object that wraps a string as well as some information about whether or not it's a special value. Something along the lines of...
public class Special<T> {
public enum Type {
NOTHING, RANDOM, SPECIFIC
}
private final Type type;
private final T specificValue;
public Special(Type type, T specificValue) {
this.type = type;
this.specificValue = specificValue;
}
public Type getType() {
return type;
}
public T getSpecificValue() {
if (type != SPECIFIC) {
throw new IllegalStateException("Value is not specific");
}
return specificValue;
}
}
The class above could be used like so:
Special<String> a = new Special<>(Special.Type.NOTHING, null);
Special<String> b = new Special<>(Special.Type.SPECIFIC, "Hello");
if (b.getType() == Special.Type.RANDOM) {
// do something
}else if (b.getType() == Special.Type.SPECIFIC) {
String val = b.getSpecificValue();
// do something else
}
A slightly more polished variant of the thing above is probably the best way, but there is a way, a much uglier way, to do it using nothing but a String field.
What you could do is to have a "magical" string instance that behaves differently from all other string instances, despite having the same value. This would be done by having something like
static final String SPECIAL_VALUE_RANDOM = new String("random");
Note the use of the String constructor, which ensures that the string becomes a unique, non-interned instance. You can then say if (vehicle == SPECIAL_VALUE_RANDOM) { ... } (note the use of == instead of .equals()) to check if that specific instance (rather than any other string that says "random") was used.
Again, this is not a particularly good way of doing this, especially if you intend to do this more than once ever. I would strongly suggest something closer to the first way.
I have an assingment for school and I am having trouble with some ArrayLists. I have an input file which has one entry at every line. This entry has an integer and up to four strings. This input file is about locations that a film is filmed. The integer is the movieID in my case and the strings are the locations. However not every film has 4 locations which means that when my program tries to load the file it returns an error because it expects 5 fields at every row and this never happens because I have movies with 1 or 2 or the locations. I use a data loader class because I have to load several different files. My other files have a specific number of entries and fields at each row so loading those isn't a problem. The load process is done by adding the file into an array list and then creating the objects needed. I know that I need the program somehow to understand the empty fields and maybe handle them dynamically, for example a movie has 3 locations so the 4th field is empty, but I haven't figured it out yet. Any suggestions? Thank you!
This is my LocationsLoader class.
package dataLoader;
import java.util.ArrayList;
import dataModel.Locations;
public class LocationsLoader extends AbstractFileLoader<Locations>{
public int constructObjectFromRow(String[] tokens, ArrayList<Locations> locations) {
int movieID;
List<String> loc = new List();
movieID = Integer.parseInt(tokens[0]);
loc = tokens[]; // What goes here?
Locations l;
l = new Locations(movieID, loc);
locations.add(l);
System.out.println(l);
//System.out.println(locations.toString());
return 0;
}
}
And this is my Locations class:
package dataModel;
public class Locations {
private int movieID;
private List<String> loc;
public Locations(int otherMovieID, List<String> otherLocations) {
this.movieID = otherMovieID;
this.loc = otherLocations;
}
public int getMovieID() {
return movieID;
}
public void setMovieID(int id) {
this.movieID = id;
}
public String getLocations(int index) {
return loc.get(index);
}
}
}
You fill an array here
String[] tokens = new String[numFields];
for (int i = 0; i < numFields; i++) {
tokens[i] = tokenizer.nextToken();
}
but arrays are fixed length, there's really no reason to use them if you can have fewer values. Fill a list instead.
List<String> tokens = new ArrayList<>();
while (tokenizer.hasNextToken()) {
String token = tokenizer.nextToken().trim();
if (!token.isEmpty()) {
tokens.add(tokenizer.nextToken());
}
}
In fact, I'm not sure why you would need to give the reader the number of expected tokens at all.
But as Dodgy pointed out, you might as well use String#split:
String[] tokens = line.split(delimiter);
which will yield empty Strings as well, but you can just ignore those in your constructObjectFromRow function.
I don't know if this is possible in Java but I was wondering if it is possible to use an object in Java to return multiple values without using a class.
Normally when I want to do this in Java I would use the following
public class myScript {
public static void main(String[] args) {
// initialize object class
cl_Object lo_Object = new cl_Object(0, null);
// populate object with data
lo_Object = lo_Object.create(1, "test01");
System.out.println(lo_Object.cl_idno + " - " + lo_Object.cl_desc);
//
// code to utilize data here
//
// populate object with different data
lo_Object = lo_Object.create(2, "test02");
System.out.println(lo_Object.cl_idno + " - " + lo_Object.cl_desc);
//
// code to utilize data here
//
}
}
// the way I would like to use (even though it's terrible)
class cl_Object {
int cl_idno = 0;
String cl_desc = null;
String cl_var01 = null;
String cl_var02 = null;
public cl_Object(int lv_idno, String lv_desc) {
cl_idno = lv_idno;
cl_desc = lv_desc;
cl_var01 = "var 01";
cl_var02 = "var 02";
}
public cl_Object create(int lv_idno, String lv_desc) {
cl_Object lo_Object = new cl_Object(lv_idno, lv_desc);
return lo_Object;
}
}
// the way I don't really like using because they get terribly long
class Example {
int idno = 0;
String desc = null;
String var01 = null;
String var02 = null;
public void set(int idno, String desc) {
this.idno = idno;
this.desc = desc;
var01 = "var 01";
var02 = "var 02";
}
public int idno() {
return idno;
}
public String desc() {
return desc;
}
public String var01() {
return var01;
}
public String var02() {
return var02;
}
}
Which seems like a lot of work considering in Javascript (I know they are different) I can achieve the same effect just doing
var lo_Object = f_Object();
console.log(lo_Object["idno"] + " - " + lo_Object[desc]);
function f_Object() {
var lo_Object = {};
lo_Object = {};
lo_Object["idno"] = 1;
lo_Object["desc"] = "test01";
return lo_Object;
}
NOTE
I know the naming convention is wrong but it is intentional because I have an informix-4gl program that runs with this program so the coding standards are from the company I work for
The best way to do this is to use HashMap<String, Object>
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
HashMap<String, Object> person =
new HashMap<String, Object>();
// add elements dynamically
person.put("name", "Lem");
person.put("age", 46);
person.put("gender", 'M');
// prints the name value
System.out.println(person.get("name"));
// asures that age element is of integer type before
// printing
System.out.println((int)person.get("age"));
// prints the gender value
System.out.println(person.get("gender"));
// prints the person object {gender=M, name=Lem, age=46}
System.out.println(person);
}
}
The advantage of doing this is that you can add elements as you go.
The downside of this is that you will lose type safety like in the case of the age. Making sure that age is always an integer has a cost. So to avoid this cost just use a class.
No, there is no such a feature, you have to type out the full type name(class name).
Or use may use val :
https://projectlombok.org/features/val.html
Also, if you use IntelliJ IDEA
try this plugin :
https://bitbucket.org/balpha/varsity/wiki/Home
I am not sure if it's possible with Java. Class is the primitive structure to generate Object. We need a Class to generate object. So, for the above code, i don't think there is a solution.
Java methods only allow one return value. If you want to return multiple objects/values consider returning one of the collections. Map, List, Queue, etc.
The one you choose will depend on your needs. For example, if you want to store your values as key-value pairs use a Map. If you just want to store values sequentially, use a list.
An example with a list:
list<Object> myList = new ArrayList<Object>();
myList.add("Some value");
return myList;
As a side note, your method create is redundant. You should use getters and setters to populate the object, or populate it through the constructor.
cl_Object lo_Object = new cl_Object(1, "test01");
The way you have it set up right now, you're creating one object to create another of the same type that has the values you want.
Your naming convention is also wrong. Please refer to Java standard naming convention:
http://www.oracle.com/technetwork/java/javase/documentation/codeconventions-135099.html#367
I am trying to add object of type Shoe into the fixed array of type Shoe, but I have a problem with it.
In the addShoe method I am trying to add reference of type Shoe to the sh array like this: sh.add(s);
when I trie to run it I get this error:
Cannot invoke add(Shoe) on the array type Shoe[]
Eclipse recommends me to change it to 'length' and it doesn't make sens
I am also thinking I could write an else part of the addShoes method like this:
public void addShoe(Shoe s) throws ShoeException
{
if(s.getId() < 0) {
throw new ShoeException(s);
}
else {
if(numShoes<=10){
sh = Arrays.add(s, numShoes);
numShoes++;
}
}
}
It is just one of the ideas. Is it the correct way to do it?
public class TestShoe {
public static void main(String[] args) {
ShoeProcessor s = new Shoe();
Shoe s1 = new Shoe(7, "Black");
Shoe s2 = new Shoe(10, "Red");
try {
s.addShoe(s1);
s.addShoe(s2);
}catch(ShoeException bex){
System.out.println("Shoe Exception: " + bex);
}
}
}
public class ShoeProcessor
{
private Shoe [] sh;
private int numShoes=0;
private ShoeComparator<Shoe> sc;
public ShoeProcessor()
{
sh = new Shoe [10];
sc=new ShoeComparator<Shoe>();
}
public void addShoe(Shoe s) throws ShoeException
{
if(s.getId() < 0) {
throw new ShoeException(s);
}
else {
sh.add(s);
numShoes++;
}
}
}
Thank you for your help
I want to add I need to use array Shoe of fixed size.
I also want to add that I don't want to extend the array sh. I can add max 10 references of type Shoe to it. This is why I am also counting number of shoes added.
Probably I'm missing something: do you want replace sh.add(s); with sh[numShoes]= s; ?
Arrays in Java have a fixed size. You have two options:
Switch to using a List. This can dynamically grow when you add more items to it. For implementation you can use an ArrayList or LinkedList.
Try using System.arraycopy to resize your array each time you need to add to it. I don't recommend this. Internally, this is actually something that ArrayList does, but you are free to do it manually if you so choose.
edit: Just saw your edit. You can do something like:
public void addToList(Shoe shoe) {
if(shoeList.size() < 10) {
shoeList.add(shoe);
}
}
shoeArrayCount = 0;
public void addToArray(Shoe shoe) {
if(shoeArrayCount < 10) {
shoeArray[shoeArrayCount] = shoe;
shoeArrayCount++;
}
}
Depending on which method you choose to inplement.
I am creating an array of customer accounts for a company called "customers". I have a method called getGasAccount which will count the number of accounts in the array.
I declared variables in the program class as:
final int MAXACCOUNTS = 10;
int intNUmber, intSelectAccount;
I set up the accounts using:
if (GasAccount.getGasAccount() < MAXACCOUNTS) {
intSelectAccount = GasAccount.getBankAccount()++;
customers[intSelectAccount] = new GasAccount();
}
I want to be able to search for a customer by their account number which is manually input when the constructor is called. I don't want to search by the intSelectAcocunt/array reference.
If I have a method called displayAccountDetails, is there another way of finding the account rather than using:
customers[intSelectAccount].displayAccountDetails();
Implement equals method in GasAccount like this
public boolean equals(Object objToCompare){
if (objToCompare != null){
return objToCompare instanceof GasAccount && ((GasAccount)objToCompare).getAccountNumber() == getAccountNumber();
}else{
return false;
}
}
Now to find the location of GasAccount object in the array and to display the account details:
java.util.List<GasAccount> gasAccountsList = (java.util.List<GasAccount>)java.util.Arrays.asList(customers);
int objectIndex = gasAccountsList.indexOf([Gas Account Object]);
if (objectIndex != -1){
gasAccountsList.get(objectIndex).displayAccountDetails();
}
Another simple approach suggested by jahroy to search by account number is :
public void getAccountDetails(int accountNumber){
java.util.List<GasAccount> gasAccountsList = (java.util.List<GasAccount>)java.util.Arrays.asList(customers);
for(GasAccount gasAccountObj : gasAccountsList){
if(gasAccountObj.getAccountNumber() == accountNumber){
gasAccountObj.displayAccountDetails();
break;
}
}
}
OR
public void getAccountDetails(int accountNumber){
for(GasAccount gasAccountObj : customers){
if(gasAccountObj.getAccountNumber() == accountNumber){
gasAccountObj.displayAccountDetails();
break;
}
}
}
The data structure that you want is a HashMap. You can do something like this.
public class AccountClass{
//You can fill in the details. I sounds like you know about constructors
//getters, setters, etc.
private HashMap<String, String> accountHash = new HashMap<String, String>();
public HashMap<String, String> getHashMap()
{
return this.accountHash;
}
}
when you want to look up an account by account number, you will be able to do something like this.
AccountClass acct = new AccountClass();
acct.getHashMap().get("1234");
assuming that you have actually put an entry with account number "1234" in your map it will return the value associated with that key.
Here is the Wikipedia article if you want to do more reading.
Edit: I have a few more things to add based on some comments.
It might be better if you made the HashMap static like this
private static HashMap<String, String> accountHash = new HashMap<String, String>();
When you declare the variable static this makes it so that you don't have to instantiate an object to access the HashMap. You can just do something like this.
AccountClass.accountHash.get();
or
AccountClass.accountHash.put();
If you want to add things to your HashMap, you need to use the put method. Here is an example.
accountHash.put("1234","My test account").
Now when you use this,
accountHash.get("1234");//you will get My test account
you will get the value associated with the "1234" key.
Keep in mind this example is just to give you an idea about how to use it. You can have a map of , , or whatever else you want.