如何对一个 ArrayList 进行排序,使其按照一组数值的列表进行排序。

huangapple 未分类评论49阅读模式
英文:

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

问题

我有一个包含食谱的 ArrayList,每个食谱都包含一系列的配料。这些食谱在 Android 应用的 UI 列表中显示,用户希望根据他们最喜欢的配料对列表进行排序。

例如,这是他们最喜欢的配料列表:

1 - 奶酪
2 - 马铃薯
3 - 金枪鱼
4 - 鸡肉

因此,食谱列表应该首先显示所有包含奶酪的配料,然后是马铃薯等等。如何使用 Java 的 stream() 实现这一点?

以下是我目前的模型类结构

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;
    }
}
英文:

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;
    }
}

答案1

得分: 0

你可以创建 comparatorPotatocomparatorCheese,然后基于它们进行排序。

  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);
    }

输出:

[[Cheese, Potato, Onions], [Potato, Cheese], [Cheese, Tomato], [Tuna, Potato, Chicken], [Chicken, Potato], [Chicken]]
英文:

You can create comparatorPotato and comparatorCheese then sort based on them

  static class Recipie {
        List&lt;String&gt; list;

        public Recipie(List&lt;String&gt; list) {
            this.list = list;
        }

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

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

        List&lt;Recipie&gt; result = recipies.stream().sorted(Comparator.comparing(r -&gt; !r.list.contains(&quot;Potato&quot;)))
                .sorted(Comparator.comparing(r -&gt; !r.list.contains(&quot;Cheese&quot;))).collect(Collectors.toList());

        System.out.println(result);
    }

, output

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

答案2

得分: 0

你的Recipe类没有使用你的Recipe类,所以你的模型可以被修改以使用Ingredient类。

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

你可以创建自己的Comparator来根据是否包含某个成分来排序Recipe。

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;
        }
    }
}

现在,你可以为每个成分创建一个Comparator,并将所有比较器链接起来。你可以使用Stream API将喜爱的成分映射到比较器,并使用thenComparing方法链接这些比较器:

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

你可以使用结果比较器来对列表进行排序:

List<Recipe> recipeList = // ... 获取recipeList
if (favoritesComparator.isPresent()) {
    recipeList.sort(favoritesComparator.get());
}
英文:

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

public class Recipe {
    List&lt;Ingredient&gt; ingredients;
    ...
}

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

public class ContainsIngredientComparator implements Comparator&lt;Recipe&gt; {

    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&lt;ContainsIngredientComparator&gt; favoritesComparator = favorites.stream()
        .map(ContainsIngredientComparator::new)
        .reduce((c1, c2) -&gt; (ContainsIngredientComparator) c1.thenComparing(c2));

You can use the result Comparator to sort the list:

List&lt;Recipe&gt; recipeList = // ... get the recipeList
if (favoritesComparator.isPresent()) {
    recipeList.sort(favoritesComparator.get());
}

huangapple
  • 本文由 发表于 2020年5月5日 04:16:56
  • 转载请务必保留本文链接:https://java.coder-hub.com/61600845.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定