【问题标题】:How do I sort an Arraylist so its collection is sorted by a list of values如何对 Arraylist 进行排序,使其集合按值列表排序
【发布时间】:2020-05-04 20:16:56
【问题描述】:

我有一个 Arraylist,其中包含食谱,每个食谱都包含一个成分列表。食谱显示在 Android 应用的 UI 列表中,用户希望根据他们最喜欢的成分对列表进行排序。

例如这是他们最喜欢的成分列表

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

因此,食谱列表应首先显示包含奶酪的所有成分,然后是土豆等。 如何使用 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;
    }
}

【问题讨论】:

  • 为什么要使用 Java 8 Streams?只需使用Collections.sort(list);
  • 请显示一些代码。
  • 我的意思是你也可以使用Stream#sorted 来获得排序的流。
  • This 可能会有所帮助,但请注意对性能的担忧。
  • @M.S.刚刚添加了一些

标签: java arraylist java-stream


【解决方案1】:

您的 Recipe 类没有使用您的 Recipe 类,因此可以修改您的模型以使用成分类。

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

您可以创建自己的比较器来排序食谱是否包含某些成分。

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

现在,您可以为每种成分创建一个比较器并将所有比较器链接起来。您可以使用 Stream API 将收藏夹成分映射到比较器,并使用 thenComparing 链接比较器:

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

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

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

【讨论】:

  • 或者只是Comparator.comparing(r -&gt; !r.getIngredients().contains(ingredient))
【解决方案2】:

您可以创建comparatorPotato 和comparatorCheese,然后根据它们进行排序

  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]]

【讨论】:

  • 你应该检查你的逻辑条件。 first &amp;&amp; !second || first &amp;&amp; !second 是多余的,因为两种选择都是相同的。此外,first &amp;&amp; second || first &amp;&amp; !second 包含 second!second 在两个备选方案中,同时具有共同的 first &amp;&amp; …,因此无论second 的内容如何,​​结果都只是first。您应该在结果中注意到包含"Cheese" "Potato" 的列表不在开头。不要手动实现这样的比较器,只需使用,例如Comparator.comparing(r -&gt; !r.list.contains("Potato")).
猜你喜欢
  • 2010-11-18
  • 1970-01-01
  • 2021-05-21
  • 2018-08-11
  • 2021-01-15
  • 2015-07-08
  • 1970-01-01
  • 2012-01-21
  • 1970-01-01
相关资源
最近更新 更多