This question already has answers here:
To use a string value as a variable name [duplicate]
(5 answers)
Closed 2 years ago.
I was just simplifying my code and I ran into a small problem which I can't solve.
So I have an activity which has a getter like so:
private String[][] Example001 ={{"String1","String2"},{"Light","Normal","Heavy"}};
public String getExerciseValue(String variableName ,int codeOrValue,int type){
switch (variableName){
case "Example001":
return Example001[codeOrValue][type];
case "Example999"
return Example999[codeOrValue][type];
}
return "default";
}
so instead of having numerous number of cases, I would rather simplify the code by something like this
public String getExerciseValue(String variableName ,int codeOrValue,int type){
return variableName[codeOrValue][type];
}
I ask for an example of working code work this case coz I have no idea how to figure this out. Thanks for any suggestions :)
This is not possible in Java. However, it is also not necessary.
Whenever you have series of numbered variable names, that's actually just a very cumbersome way of implementing an array:
private String[][][] examples = {
{
{ "String1", "String2" },
{ "Light", "Normal", "Heavy" }
}
};
public String getExerciseValue(int exampleNumber, int codeOrValue, int type) {
return examples[exampleNumber - 1][codeOrValue][type];
}
Suggest you to use HashMap, and put each array as a value with your preferred name in it. Something like it:
Map<String, String[][]> examples = new HashMap<>();
examples.put("Example001", Example001);
You can then easily retrieve your element with its names and indexes as you needed.
examples.get("Example001")[codeOrValue][type]
Related
While I know that this code should work to return the index, for some reason it's skipping the if statement and going straight to the else, when I know that the name is within the array, with the array that I'm using for testing. Won't even print the "if - reading" line.
public int find(String name)
{
int index = 0;
for(int i = 0; i < this.shoppingItems.length;i++)
{
if(this.shoppingItems[i].equals(name))
{
System.out.println("If - Reading");
index = i;
}
else
{
index = -1;
}
}
System.out.println(index);
return index;
}
//Main
ShoppingItem[] items = new ShoppingItem[]{new ShoppingItem("Eggs",3.2),new ShoppingItem("Bread",2.8),new ShoppingItem("Bacon",9),new ShoppingItem("Peas",2),new ShoppingItem("Spinach",4),new ShoppingItem("Chocolate",8)};
ShoppingList itemList = new ShoppingList(items);
itemList.find("Bread");
"While I know that this code should work to return the index, for some reason it's skipping the if statement and going straight to the else"
Stop! Java is not wrong; your code is, and it shouldn't work. Your if statement is not being skipped; it's just that the condition is always false, because this.shoppingItems[i] is a ShoppingItem object, and you are comparing it with name, which is a string. A ShoppingItem object is never equal to a string.
Presumably, what you want to test is whether the ShoppingItem object's name is equal to that string. Presumably, your class has a getName method, so you should test:
if(this.shoppingItems[i].getName().equals(name)) {
// ...
}
This is a common kind of programming error, perhaps because it's often acceptable in natural language to say one thing when you mean something closely related; e.g. you might say "I asked the help desk" when really you asked a person at the help desk, you did not ask the desk itself. This is a bit like that; you want the item's name to equal name, not the item itself.
Unless you are compelled to use arrays, you can make things much easier by using lists. They have quite a few useful features.
List<String> items = List.of("bread", "juice", "eggs", "milk");
System.out.println(find("eggs"));
System.out.println(find("butter"));
public int find(String name) {
return items.indexOf(name);
}
Prints
2
-1
That method of the List interface pretty much negates the need to write you own method. I just did it for demonstration purposes.
This example was using a List of Strings and not ShoppingItem class. You could get a List<ShoppingItem> to work by overriding the equals method in your class (something you should get in the habit of anyway).
And here is a taste of how would do it with Stream (java 8+). It presumes list is a simple array of ShoppingItem.
public int find(String name) {
return IntStream.range(0, list.length).filter(
i -> list[i].item.equalsIgnoreCase(name)).findFirst().orElse(-1);
}
This question already has answers here:
Java: Check if enum contains a given string?
(32 answers)
Closed 3 years ago.
I need to find if given String is not in the list of ENUMs.
These Strings come back with spaces, i.e.: "CHILD CARE", "CREDIT CARDS", etc...
Any other ExpenseType should be mapped to OTHER, except HOA. HOA should be completely ignored.
My ENUMs are as follows:
public enum ExpenseType {
AUTOLOAN("AUTO LOAN"),
ALIMONY("ALIMONY"),
CHILDCARE("CHILD CARE"),
CREDITCARDS("CREDIT CARDS"),
INSTALLMENTLOANS("INSTALLMENT LOANS"),
FOOD("FOOD"),
UTILITIES("UTILITIES"),
TRANSPORTATION("TRANSPORTATION"),
OTHER("OTHER");
private String expenseType;
ExpenseType(String expenseType) {
this.expenseType = expenseType;
}
#Override public String toString() {
return this.expenseType;
}
}
The way I am doing this now is as follows:
String expenseDescription = expense.getExpenseDesc().replaceAll(" ", "");
if(EnumUtils.isValidEnum(ExpenseType.class, expenseDescription)) {
monthlyExpenses.setType(ExpenseType.valueOf(expenseDescription).toString());
}
else if(!expenseDescription.equals("HOA")) {
monthlyExpenses.setType(ExpenseType.OTHER.toString());
}
Does anyone know a better way to do this?
Why not use getEnum to get Enum if applicable (check for null or use Optional
if needed)
ExpenseType monthlyExpenses = EnumUtils.getEnum(ExpenseType.class, expenseDescription);
Gets the enum for the class, returning null if not found.
This method differs from Enum.valueOf(java.lang.Class, java.lang.String) in that it does not throw an exception for an invalid enum name.
Also prefer adding to enum a code (String) as a reference, which won't contains spaces and special characters, e.g.
//...
CHILDCARE("CHILD_CARE","CHILD CARE"),
//...
private String expenseType;
private String expenseTypeCode;
ExpenseType(String expenseType, String expenseTypeCode) {
this.expenseType = expenseType;
this.expenseTypeCode = expenseTypeCode;
}
Here is another alternative.
Map<String, String> codes = Arrays.stream(ExpenseType.values()).collect(
Collectors.toMap(ExpenseType::toString, ExpenseType::name));
codes.put("HOA","TBD");
String[] submittedCodes = { "CREDIT CARDS", "FOOD", "UTILITIES", "UNKNOWN"
};
for (String c : submittedCodes) {
String expenseType = codes.getOrDefault(c,"OTHER");
System.out.println(expenseType);
}
First, I didn't see a reason to remove the spaces from the submitted code unless you are concerned about addition of extra spaces creeping in. In that case you should probably also remove tabs.
Since you are already using the enum value to compare to the name, I figured I would just ignore the name as they are effectively the same.
The map is used only to allow a null to be returned in case of a missing key.
The enum was only used to conveniently populate the map.
I did not know exactly how to handle HOA. But all of this is just another alternative for you to possibly investigate as you can rearrange the keys and values, etc to suit your requirements.
Harry Potter Which Character Are You Quiz.
So I want to take each option, and the character(s) associated with each option (below the options is each character(s) separated by a comma ex. 1.Acid Pops Neville Longbottom, 3. Bertie Bott's Every Flavour Beans Luna Lovegood Nymphadora Tonks....I want to send the option, character(s) in the main method and send it as a String to the Question class and store it in an Arraylist of type Answer not String. And in the Answer class will be passed only what the user selects so for ex. 2. Sherbert Lemons and Albus Dumbledore.
String[] questions =
{
"Favourite sweet",
};
String [][] options =
{
{"1.Acid Pops","2.Sherbert Lemons","3.Bertie Bott's Every Flavour Beans",
"4.Cake","5.Hagrid's Rock Cakes","6.Chocolate Frogs","7.Ginger Newt",
"8.I hate sweets\n"},
{"Neville Longbottom","Albus Dumbledore", "Luna Lovegood, Nymphadora
Tonks", "Dobby, Arthur Weasley", "Rubeus Hagrid",
"Harry Potter, Ron Weasley", "Minerva McGonagall, Hermione Granger,
Dolores Umbridge, Sybill Trelawney",
"Severus Snape, Tom Riddle, Sirius Black, Bellatrix Lestrange, Draco
Malfoy, Lucius Malfoy"}
};
Here is my for loop in my main method:
for (int i =0; i < questions.length; i ++){
String aQuestion = questions[i];
Question q = new Question(aQuestion);
System.out.println(aQuestion);
for(int j=0; j < options[i].length; j++){
q.setAnswers(options[i][j], options[i+1][j]);
System.out.println(options[i][j]);
}
}
Here's my Question class:
private String question;
public ArrayList<Answer> answers = new ArrayList<Answer>();
public Question(String q){
question = q;
}
public void setAnswers(String options, String options2){
answers.add(options);
answers.add(options2);
}
Sorry if this doesn't make sense.
I also don't understand why you have an arraylist of type: Answer that matches a class name you have in your program. If that also makes sense.
Here is the problem, You cannot add anything(any other object) to your List<Answer> except for Answer objects.
See the following lines Line 1 and Line 2
public void setAnswers(String options, String options2){
answers.add(options); //LINE 1
answers.add(options2); //LINE 2
}
Now, I am not really sure how your Answer really looks like. But if it has got something to do with the options. It can have the following constructor in Answer class
Answer(String option){
this.option = option;
}
And you can modify your code to look something like this
public void setAnswers(String options, String options2){
answers.add(new Answer(options)); //LINE 1
answers.add(new Answer(options)); //LINE 2
}
I also don't understand why you have an arraylist of type
Collections in java were made typed to avoid accidental addition of wrong object to it. You can very well omit the type from the declaration but that is not recommended.
As an alternative solution you can either:
Change the type of ArrayList<Answer> answers to more generic one like Serializable or,
Wrap String options1 and options2 and convert them into Answer type and then add them to list.
I'll prefer second option.
Convert: Create a method in Answer class which return Answer object, you can make it static
public static Answer getAnswerFromString(String answer) {
// Logic to create Answer object from string
}
Then modify this method as below to add answer to the list:
public void setAnswers(String options, String options2){
answers.add(Answer.getAnswerFromString(options));
answers.add(Answer.getAnswerFromString(options2));
}
Or you can add a constructer with String parameter if it make sense as pointed in other answer.
This question already has answers here:
Why can't enum's constructor access static fields?
(5 answers)
Closed 6 years ago.
I have an enum with values like this (the example just shows a few of the values but you will catch on): _800, _830, _900, _24HOURS, CLOSED
These have a corresponding value, so I added to my enum, which you can do in Java, a value field and a getter and setter for the value, like this (for space sake I do not show the getter and setter but they are the standard ones):
enum Hours {
_800("08:00"),
_830("08:30"),
CLOSED("Closed"),
APPT("By Appt.")
// etc
;
Hours(String v) {
val = v;
}
String val;
}
I also want to be able to go the other direction, that is, if I have a value (e.g. "08:00") I want it to return the enum _800. So to the enum I added a map:
static Map<String,String> valToEnumMap = new HashMap();
then I added this to my constructor:
Hours(String v) {
val = v;
valToEnumMap.put(v, this);
}
and a new method:
Hours valToEnum(String v) {
return valToEnumMap(v);
}
but when I try running it I get an initialization error at the point where it tries to insert into the map. I have tried other things like
valToEnumMap.put(v, valueOf(name());
but the same error. I did find a workaround but it is very slow, so I wonder what I did wrong? Here is the workaround I used which is slow:
public static OfficeHoursTimes valToEnum(String val) {
for (OfficeHoursTimes o : OfficeHoursTimes.values()) {
if (o.getVal().equals(val)) {
return o;
}
}
return null;
}
But there has to be a better way
The problem is that you're trying to use the map before it's initialized, since your enum instances get created first.
You want to declare your map like this:
static final Map<String,Hours> valToEnumMap = _createValueMap();
and then
private static Map<String,Hours> _createValueMap()
{
Map<String, Hours> map = new HashMap<>();
//...iterate through values() and put them all in the map ...
return map;
}
At first glance, it seems your map is defined wrong.
Try
static Map<String,Hours> valToEnumMap = new HashMap<String,Hours>();
This question already has answers here:
What's the best way to implement `next` and `previous` on an enum type?
(7 answers)
Closed 7 years ago.
I have an enum in Java as following:
public enum Cars
{
Sport,
SUV,
Coupe
}
And I need to get the next value of the enum. So, assuming I have a variable called myCurrentCar:
private Cars myCurrentCar = Cars.Sport;
I need to create a function that when called set the value of myCurrentCar to the next value in the enum. If the enum does not have anymore values, I should set the variable to the first value of the enum.
I started my implementation in this way:
public Cars GetNextCar(Cars e)
{
switch(e)
{
case Sport:
return SUV;
case SUV:
return Coupe;
case Coupe:
return Sport;
default:
throw new IndexOutOfRangeException();
}
}
Which is working but it's an high maitenance function because every time I modify the enum list I have to refactor the function.
Is there a way to split the enum into an array of strings, get the next value and transform the string value into the original enum? So in case I am at the end of the array I simply grab the first index
Yeah sure, it goes like this
public Cars getNextCar(Cars e)
{
int index = e.ordinal();
int nextIndex = index + 1;
Cars[] cars = Cars.values();
nextIndex %= cars.length;
return cars[nextIndex];
}