简体   繁体   中英

How do I sort an Arraylist so its collection is sorted by a list of values

I have an Arraylist which contains recipies and each recipe contains a list of ingredients. The recipies is shown in a UI list of an Android app and the useres wants to sort the list based on the ingredients they like most.

For example this is the list of ingredients they like most

1 - Cheese
2 - Potato
3 - Tuna
4 - Chicken

So the list of recipies shall show first all the ingredients that contains cheese and then potato etc. How do I archive this with java stream() ?

Here is how my model classes is at the moment

public class Recipe {

    String[] ingredients;
    private String description;
    private String title;


    public String[] getIngredients() {
        return ingredients;
    }

    public void setIngredients(String[] ingredients) {
        this.ingredients = ingredients;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}

.

public class Ingredient {

    String title;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}

You can create comparatorPotato and comparatorCheese then sort based on them

  static class Recipie {
        List<String> list;

        public Recipie(List<String> list) {
            this.list = list;
        }

        @Override
        public String toString() {
            return list.toString();
        }
    }

    public static void main(String[] args) {
               List<Recipie> recipies = new ArrayList<>();
        recipies.add(new Recipie(Arrays.asList("Cheese", "Potato", "Onions")));
        recipies.add(new Recipie(Arrays.asList("Tuna", "Potato", "Chicken")));
        recipies.add(new Recipie(Arrays.asList("Potato", "Cheese")));
        recipies.add(new Recipie(Arrays.asList("Chicken")));
        recipies.add(new Recipie(Arrays.asList("Chicken", "Potato")));
        recipies.add(new Recipie(Arrays.asList("Cheese", "Tomato")));

        List<Recipie> result = recipies.stream().sorted(Comparator.comparing(r -> !r.list.contains("Potato")))
                .sorted(Comparator.comparing(r -> !r.list.contains("Cheese"))).collect(Collectors.toList());

        System.out.println(result);
    }

, output

[[Cheese, Potato, Onions], [Potato, Cheese], [Cheese, Tomato], [Tuna, Potato, Chicken], [Chicken, Potato], [Chicken]]

Your Recipe class is not using your Recipe class, so your model can be modified to use the Ingredient class.

public class Recipe {
    List<Ingredient> ingredients;
    ...
}

You can create your own Comparator to sort if a Recipe has some ingredient.

public class ContainsIngredientComparator implements Comparator<Recipe> {

    private Ingredient ingredient;

    public ContainsIngredientComparator(Ingredient ingredient) {
        this.ingredient = ingredient;
    }   

    @Override
    public int compare(Recipe r1, Recipe r2) {
        if (r1.getIngredients().contains(ingredient)) {
            if (r2.getIngredients().contains(ingredient)) {
                return 0;
            } else {
                return -1;
            }
        } else if (r2.getIngredients().contains(ingredient)) {
            return 1;
        } else {
            return 0;
        }
    }
}

Now, you can create a Comparator for each ingredient and chain all the comparators. You can use the Stream API to map the favorites ingredients to comparators and use thenComparing to chain the comparators:

Optional<ContainsIngredientComparator> favoritesComparator = favorites.stream()
        .map(ContainsIngredientComparator::new)
        .reduce((c1, c2) -> (ContainsIngredientComparator) c1.thenComparing(c2));

You can use the result Comparator to sort the list:

List<Recipe> recipeList = // ... get the recipeList
if (favoritesComparator.isPresent()) {
    recipeList.sort(favoritesComparator.get());
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM