根据单个或多个属性的用户自定义输入对集合进行排序
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);
}
}
我有 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);
}
}