Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to choose an ArrayList based on user input?

I want to make the program choose from an ArrayList based on my Scanner Input.
Like, I write breakfast and than sweet, and it has to randomize the list breakfastSweet and print me the randomized index.

I am still learning Java, I am just playing around and trying to code little projects to train it.

import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);

        // program begins here, you get asked what kind of lunch you want to eat
        // after asking for the meal type and answering it, it goes to the next question

        System.out.println("Hi, welcome to Recipe-Randomizer! What kind of meal do you want, breakfast, lunch or maybe dinner?");
        System.out.print("Type one of the give choices now: ");
        String mealType = scanner.nextLine();
        System.out.print("So you want to eat for " + mealType + ". Do you want to eat some sweet or savory " + mealType + "?\nType in one of the given choices: ");
        String flavor = scanner.nextLine();
        System.out.println("A " + flavor + " " + mealType + "? Well, let's see what we have here.\nI am going to pick a random recipe.\nPlease wait...");


        // list of meals, list name describes
        ArrayList<String> breakfastSweet = new ArrayList();
        

        ArrayList<String> breakfastSavory = new ArrayList();

        ArrayList<String> lunchSweet = new ArrayList();
        

        ArrayList<String> lunchSavory = new ArrayList();
        

        ArrayList<String> dinnerSweet = new ArrayList();
        

        ArrayList<String> dinnerSavory = new ArrayList();
       

        GetRandomFromList.outputMeal(mealType, flavor, dinnerSavory); // doesn't make sense to put the list already in, I want it to automatically select the right list.

    }
}

And here is the class I have already written:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

import java.util.ArrayList;
import java.util.Random;

public class GetRandomFromList {

    private static String randomList(ArrayList<String> list) {
        Random rand = new Random();
        return list.get(rand.nextInt(list.size()));

    }

    public static void outputMeal(String mealType, String flavor, ArrayList<String> list){ // the list should be chosen automatically, so my code doesn't work as I want it to work
        if (mealType.equals("breakfast") && flavor.equals("sweet")){
            System.out.println("What about " + GetRandomFromList.randomList() + "?");
        }
    }
}

Can I somehow store a list in a variable, maybe like this:

if (mealType.equals("breakfast") && flavor.equals("sweet")){
            // here make a variable of the breakfastSweet list
}

I know it’s hard to understand me, but English isn’t my main language, hope its understandble.

>Solution :

To me GetRandomFromList doesn’t make sense, unless GetRandomFromList contains all the data, instead, just assign a reference of the chosen List to another variable and then shuffle it to get a random value, for example…

// Previously created lists
Random rand = new Random();

Scanner scanner = new Scanner(System.in);
System.out.println("Hi, welcome to Recipe-Randomizer! What kind of meal do you want, breakfast, lunch or maybe dinner?");
System.out.print("Type one of the give choices now: ");
String mealType = scanner.nextLine();
System.out.print("So you want to eat for " + mealType + ". Do you want to eat some sweet or savory " + mealType + "?\nType in one of the given choices: ");
String flavor = scanner.nextLine();
System.out.println("A " + flavor + " " + mealType + "? Well, let's see what we have here.\nI am going to pick a random recipe.\nPlease wait...");

ArrayList<String> userChoice = null;
if (mealType.equals("breakfast") && flavor.equals("sweet")) {
    userChoice = breakfastSweet;
} else if {...}

if (userChoice != null) {
    Collections.shuffle(userChoice, rand);
    String value = userChoice.get(0);
}

As with most things, there are more than one way to skin this cat. For example, you could Maps to combine the type/flavors together or your could create a POJO which has information about it’s type/flavor associated directly with it

POJO, with List filter…

public class Meal {

    public enum Type {
        BREAKFAST, LUNCH, DINNER;

        public static Type forType(String value) {
            try {
                return Type.valueOf(value.toUpperCase());
            } catch (IllegalArgumentException exp) {
                return null;
            }
        }
    }

    public enum Flavor {
        SWEET, SAVORY;

        public static Flavor forFlavor(String value) {
            try {
                return Flavor.valueOf(value.toUpperCase());
            } catch (IllegalArgumentException exp) {
                return null;
            }
        }
    }

    private Type type;
    private Flavor flavor;
    private String description;

    public Meal(Type type, Flavor flavor, String description) {
        this.type = type;
        this.flavor = flavor;
        this.description = description;
    }

    public Type getType() {
        return type;
    }

    public Flavor getFlavor() {
        return flavor;
    }

    public String getDescription() {
        return description;
    }

    public boolean matches(Type type, Flavor flavor) {
        return getType() == type && getFlavor() == flavor;
    }
}

So, this defines the expected type/flavors and then allows you to define a meal of a specific type/flavor and provides a simple matches method to determine if the Meal is of a specific type/flavor, because I’m lazy.

Then we can do something like…

List<Meal> meals = new ArrayList<>(16);

// Get user input

Meal.Type type = Meal.Type.forType(mealType.toUpperCase());
Meal.Flavor flavor = Meal.Flavor.forFlavor(flavorValue.toUpperCase());

if (type != null && flavor != null) {
    List<Meal> matchingMeals = new ArrayList<>(16);
    for (Meal meal : meals) {
        if (meal.matches(type, flavor)) {
            matchingMeals.add(meal);
        }
    }
    Collections.shuffle(matchingMeals);
    Meal meal = matchingMeals.get(0);
    System.out.println(meal.getDescription());
} else {
    if (type == null) {
        System.out.println(mealType + " is not a valid type");
    }
    if (flavor == null) {
        System.out.println(flavorValue + " is not a valid flavor");
    }
}

to look up a random meal.

Now, because you should be running in Java 8+, you could also replace…

List<Meal> matchingMeals = new ArrayList<>(16);
for (Meal meal : meals) {
    if (meal.matches(type, flavor)) {
        matchingMeals.add(meal);
    }
}

with…

Predicate<Meal> filter = meal -> meal.matches(type, flavor);
meals.stream().filter(filter).collect(Collectors.toList());

but that might be a bit of an ask

Map

Or, we can use a Map of some kind to link the List of data with a specific "key".

Since you have a "composite" key style (you strictly don’t need to, but I like having the flavour and type separated), I started with a MealKey concept.

public class MealKey {
    private Type type;
    private Flavor flavor;

    public MealKey(Type type, Flavor flavor) {
        this.type = type;
        this.flavor = flavor;
    }

    @Override
    public int hashCode() {
        int hash = 3;
        hash = 97 * hash + Objects.hashCode(this.type);
        hash = 97 * hash + Objects.hashCode(this.flavor);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final MealKey other = (MealKey) obj;
        if (this.type != other.type) {
            return false;
        }
        if (this.flavor != other.flavor) {
            return false;
        }
        return true;
    }
    
}

The important thing here is to ensure that any instance of a key with the same type/flavor always returns the same hashCode

I then modified the POJO to make it simpler/easier to deal with…

public enum Type {
    BREAKFAST, LUNCH, DINNER;

    public static Type forType(String value) {
        try {
            return Type.valueOf(value.toUpperCase());
        } catch (IllegalArgumentException exp) {
            return null;
        }
    }
}

public enum Flavor {
    SWEET, SAVORY;

    public static Flavor forFlavor(String value) {
        try {
            return Flavor.valueOf(value.toUpperCase());
        } catch (IllegalArgumentException exp) {
            return null;
        }
    }
}

public class Meal {

    private String description;

    public Meal(String description) {
        this.description = description;
    }

    public String getDescription() {
        return description;
    }
}

Then we fill our Map with the values we want

Map<MealKey, List<Meal>> meals = new HashMap<>();
// Fill the meals
List<Meal> breakfastSweet = new ArrayList<>();
// Add some meals to the list
meals.put(new MealKey(Type.BREAKFAST, Flavor.SWEET), breakfastSweet);

And then we can look up the meals list based on the user input…

// Get user input
Type type = Type.forType(mealType.toUpperCase());
Flavor flavor = Flavor.forFlavor(flavorValue.toUpperCase());

if (type != null && flavor != null) {
    MealKey key = new MealKey(type, flavor);
    List<Meal> mealsList = meals.get(key);
    if (mealsList != null) {
        Collections.shuffle(mealsList);
        System.out.println(mealsList.get(0).getDescription());
    }
} else {
    if (type == null) {
        System.out.println(mealType + " is not a valid type");
    }
    if (flavor == null) {
        System.out.println(flavorValue + " is not a valid flavor");
    }
}

nb: You could simply the "key" by simply using a String of "type" + "value" if you really wanted to 😉

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading