根据单个或多个属性的用户自定义输入对集合进行排序

Sort collection according to user custom input by single or multiple attributes

我有 Item 对象的集合,class Item 如下 ->

class Item {
  String id;
  String brand;
  Integer price;
  Date publishedDate;
}

现在,我想根据用户输入进行排序。用户可以根据自己的选择对它进行排序,例如品牌、价格或发布日期,甚至可以使用多个参数。喜欢品牌和价格或价格和发布日期。

我见过 Comparator 按多个参数排序,但它也有限制,而且有预定义的参数。所以基本上用户可以按任何输入进行排序,排序机制可以在不更改任何代码的情况下处理。

我得到一些使用战略设计模式的提示,但无法在此处实施来解决它。

您可以为每个字段的比较器使用静态映射,并从中构建一个组合的比较器: 您仍然必须使比较器为 null 安全并检查字段名称...

class Item {
    String id;
    String brand;
    Integer price;
    Date publishedDate;

    public Item(String id, String brand, Integer price, Date publishedDate) {
        super();
        this.id = id;
        this.brand = brand;
        this.price = price;
        this.publishedDate = publishedDate;
    }

    static Map<String, Comparator<Item>> comparatorMap = new HashMap<String, Comparator<Item>>() {
        {
            put("id", new Comparator<Item>() {
                @Override
                public int compare(Item o1, Item o2) {
                    return o1.id.compareTo(o2.id);
                }
            });
            put("brand", new Comparator<Item>() {
                @Override
                public int compare(Item o1, Item o2) {
                    return o1.brand.compareTo(o2.brand);
                }
            });
            put("price", new Comparator<Item>() {
                @Override
                public int compare(Item o1, Item o2) {
                    return o1.price.compareTo(o2.price);
                }
            });
            put("publishedDate", new Comparator<Item>() {
                @Override
                public int compare(Item o1, Item o2) {
                    return o1.publishedDate.compareTo(o2.publishedDate);
                }
            });
        }
    };

    @Override
    public String toString() {
        return "Item [id=" + id + ", brand=" + brand + ", price=" + price + ", publishedDate=" + publishedDate + "]";
    }

    static class ItemComparator implements Comparator<Item> {
        private List<Comparator<Item>> comparators;

        ItemComparator(String... fields) {
            comparators = new ArrayList<>();
            for (String field : fields) {
                comparators.add(comparatorMap.get((field)));
            }
        }

        @Override
        public int compare(Item o1, Item o2) {
            int result = 0;
            for (Comparator comparator : comparators) {
                result = comparator.compare(o1, o2);
                if (result != 0) {
                    return result;
                }
            }
            return result;
        }

    }

    static List<Item> sort(List<Item> list, String... fields) {
        Collections.sort(list, new ItemComparator(fields));
        return list;
    }

    public static void main(String[] args) {
        List<Item> list = new ArrayList<>();
        list.add(new Item("B", "A", 5, new Date()));
        list.add(new Item("A", "B", 7, new Date()));

        sort(list, "id", "price");
        System.out.println(list);
    }
}

编辑

使用比较/然后比较的版本

使用反射获取吸气剂时可以省略映射...

class Item {
    String id;
    String brand;
    Integer price;
    Date publishedDate;

    public Item(String id, String brand, Integer price, Date publishedDate) {
        super();
        this.id = id;
        this.brand = brand;
        this.price = price;
        this.publishedDate = publishedDate;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public Integer getPrice() {
        return price;
    }

    public void setPrice(Integer price) {
        this.price = price;
    }

    public Date getPublishedDate() {
        return publishedDate;
    }

    public void setPublishedDate(Date publishedDate) {
        this.publishedDate = publishedDate;
    }

    static Map<String, Comparator<Item>> comparatorMap = new HashMap<String, Comparator<Item>>() {
        {
            put("id", Comparator.comparing(Item::getId));
            put("brand", Comparator.comparing(Item::getBrand));
            put("price", Comparator.comparing(Item::getPrice));
            put("publishedDate", Comparator.comparing(Item::getPublishedDate));
        }
    };

    static List<Item> sort(List<Item> list, String... fields) {
        Comparator comparator = null;
        for (String field : fields) {
            comparator = (comparator == null) ?  comparatorMap.get((field))
                : comparator.thenComparing(comparatorMap.get((field)));
        }

        if (comparator != null) {
            Collections.sort(list, comparator);
        }
        return list;
    }

    @Override
    public String toString() {
        return "Item [id=" + id + ", brand=" + brand + ", price=" + price + ", publishedDate=" + publishedDate + "]";
    }

    public static void main(String[] args) {
        List<Item> list = new ArrayList<>();
        list.add(new Item("B", "A", 5, new Date()));
        list.add(new Item("A", "B", 7, new Date()));

        sort(list, "id", "price");
        System.out.println(list);
    }
}