- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想通过比较字符串值或枚举值来按升序和降序对 ArrayList
进行排序。
这是我想要排序的ArrayList:
List<Issue> issues;
列表将根据我赋予函数的两个参数(field
和 sort
)进行排序:
private List<Issue> sortList(List<Issue> list, String field, String sort) {
// My code goes here
}
因此,我们假设 field
值为 title
,sort
值为 DESC
那么我想按提交的 title
对列表中的所有 Issue
元素进行排序,这就是我尝试过的:
return list.stream().sorted((i1, i2) -> String.compare(i2.getTitle(), i1.getTitle())).collect(Collectors.toList());
但这会产生以下错误:
The method compare(String, String) is undefined for the type String
对于枚举,我不知道如何比较它们的值。
我该如何解决这个问题?
问题:
public class Issue {
private IssueElementEnum issueElement;
private IssueTypeEnum issueType;
private String title;
// Getters and setters
}
IssueElementEnum:
public enum IssueElementEnum {
PROFILE {
@Override
public String toString() {
return "Profil";
}
}
ROLE {
@Override
public String toString() {
return "Rôle";
}
},
User {
@Override
public String toString() {
return "Utilisateur";
}
}
}
IssueTypeEnum:
public enum IssueTypeEnum {
PROFILE {
@Override
public String toString() {
return "Sans Profil";
}
},
ROLE {
@Override
public String toString() {
return "Sans Rôle";
}
},
USER {
@Override
public String toString() {
return "Sans Utilisateur";
}
}
}
有时,我想对包含多个字段的列表进行排序(例如,按 title
升序对列表进行排序,然后按 issueElement.toSting()
排序)降序排列,为此我创建了以下类:
public class SortDTO implements ISort {
public static final String ASC = "ASC";
public static final String DESC = "DESC";
private String field;
private String sort;
public GridSortDTO() {
this(null, null);
}
public GridSortDTO(final String field, final String sort) {
super();
this.field = field;
this.sort = sort;
}
@Override
public String getField() {
return field;
}
@Override
public void setField(final String field) {
this.field = field;
}
@Override
public String getSort() {
return sort;
}
@Override
public void setSort(final String type) {
this.sort = type;
}
@Override
public String toString() {
return String.format("Sort[field=%s, sort=%s]", this.field, this.sort);
}
}
public interface ISort {
String getField();
void setField(final String field);
String getSort();
void setSort(final String type);
}
然后我的排序信息存储在这个数组中:GridSortDTO[]排序
。
例如 sorts
将包含以下信息:
[{"field":"title","sort":"asc"},{"field":"issueElement","sort":"desc"}]
我该如何实现这个?
最佳答案
不清楚您想要的 enum
类型的顺序、声明顺序(PROFILE、ROLE、USER
)或其 toString()< 的字典顺序
表示。
在后一种情况下,您可以将该方法实现为
private List<Issue> sortList(List<Issue> list, String field, String sort) {
Function<Issue,String> f;
switch(field) {
case "Title": f = Issue::getTitle; break;
case "IssueElement": f = i -> i.getIssueElement().toString(); break;
case "IssueType": f = i -> i.getIssueType().toString(); break;
default: throw new IllegalArgumentException("unknown property '"+field+"'");
}
Comparator<Issue> cmp = Comparator.comparing(f);
if("DESC".equalsIgnoreCase(sort)) cmp = cmp.reversed();
else if(!"ASC".equalsIgnoreCase(sort))
throw new IllegalArgumentException("invalid sort '"+sort+"'");
return list.stream().sorted(cmp).collect(Collectors.toList());
}
如果您想使用 enum
声明顺序,那么您的代码会稍微不太常见:
private List<Issue> sortList(List<Issue> list, String field, String sort) {
Comparator<Issue> cmp;
switch(field) {
case "Title": cmp = Comparator.comparing(Issue::getTitle); break;
case "IssueElement": cmp = Comparator.comparing(Issue::getIssueElement); break;
case "IssueType": cmp = Comparator.comparing(Issue::getIssueType); break;
default: throw new IllegalArgumentException("unknown property '"+field+"'");
}
if("DESC".equalsIgnoreCase(sort)) cmp = cmp.reversed();
else if(!"ASC".equalsIgnoreCase(sort))
throw new IllegalArgumentException("invalid sort '"+sort+"'");
return list.stream().sorted(cmp).collect(Collectors.toList());
}
您还可以维护现有订单的映射,而不是使用 switch
语句,这提供了更大的灵 active :
// in Java 9, you should replace Arrays.asList(...) with List.of(...)
static final Map<List<String>,Comparator<Issue>> ORDER;
static {
Map<List<String>,Comparator<Issue>> m = new HashMap<>();
Comparator<Issue> c = Comparator.comparing(Issue::getTitle);
m.put(Arrays.asList("Title", "asc"), c);
m.put(Arrays.asList("Title", "desc"), c.reversed());
c = Comparator.comparing(Issue::getIssueElement);
m.put(Arrays.asList("IssueElement", "asc"), c);
m.put(Arrays.asList("IssueElement", "desc"), c.reversed());
c = Comparator.comparing(Issue::getIssueType);
m.put(Arrays.asList("IssueType", "asc"), c);
m.put(Arrays.asList("IssueType", "desc"), c.reversed());
ORDER = Collections.unmodifiableMap(m);
}
private List<Issue> sortList(List<Issue> list, String field, String sort) {
Comparator<Issue> cmp = ORDER.get(Arrays.asList(field, sort.toLowerCase(Locale.ROOT)));
if(cmp == null)
throw new IllegalArgumentException("property '"+field+"', sort '"+sort+"'");
return list.stream().sorted(cmp).collect(Collectors.toList());
}
<小时/>
这种方法可以适应您的新要求,不过,我强烈建议稍微重新设计:
enum Direction { ASCENDING, DESCENDING }
public interface ISort {
String getField();
void setField(final String field);
Direction getSort();
void setSort(final Direction type);
}
调整实现很简单,但您应该避免允许 null
作为排序方向,因为这样,它本质上只是两个合法值中的一个:
public class SortDTO implements ISort {
private String field;
private Direction sort;
public SortDTO() { this(null, Direction.ASCENDING); }
public SortDTO(String field, Direction sort) {
this.field = field;
this.sort = sort;
}
public String getField() { return field; }
public void setField(String field) { this.field = field; }
public Direction getSort() { return sort; }
public void setSort(Direction sort) { this.sort = Objects.requireNonNull(sort); }
@Override
public String toString() {
return String.format("Sort[field=%s, sort=%s]", this.field, this.sort);
}
}
我们使用不可变的键类型来增强这些类型,该类型能够捕获 ISort
实现的当前状态,并具有适当的 equals
和 hashCode
实现:
final class SortKey {
final String field;
final Direction direction;
private SortKey(String f, Direction d) { field=f; direction=d; }
@Override
public int hashCode() {
return field.hashCode()*2+direction.ordinal();
}
@Override
public boolean equals(Object obj) {
if(this == obj) return true;
if(!(obj instanceof SortKey)) return false;
SortKey that = (SortKey)obj;
return this.direction == that.direction && this.field.equals(that.field);
}
static SortKey of(String field, Direction dir) {
return new SortKey(Objects.requireNonNull(field), Objects.requireNonNull(dir));
}
static SortKey of(ISort s) {
return of(s.getField(), s.getSort());
}
}
然后,调整后的解决方案可能如下所示
static final Map<SortKey,Comparator<Issue>> ORDER;
static {
Map<SortKey,Comparator<Issue>> m = new HashMap<>();
Comparator<Issue> c = Comparator.comparing(Issue::getTitle);
m.put(SortKey.of("Title", Direction.ASCENDING), c);
m.put(SortKey.of("Title", Direction.DESCENDING), c.reversed());
c = Comparator.comparing(Issue::getIssueElement);
m.put(SortKey.of("IssueElement", Direction.ASCENDING), c);
m.put(SortKey.of("IssueElement", Direction.DESCENDING), c.reversed());
c = Comparator.comparing(Issue::getIssueType);
m.put(SortKey.of("IssueType", Direction.ASCENDING), c);
m.put(SortKey.of("IssueElement", Direction.DESCENDING), c.reversed());
ORDER = Collections.unmodifiableMap(m);
}
private List<Issue> sortList(List<Issue> list, ISort... order) {
if(order.length == 0) return new ArrayList<>(list);
Comparator<Issue> cmp = ORDER.get(SortKey.of(order[0]));
if(cmp == null) throw new IllegalArgumentException(order[0].toString());
for(int ix = 1; ix < order.length; ix++) {
Comparator<Issue> next = ORDER.get(SortKey.of(order[ix]));
if(next == null) throw new IllegalArgumentException(order[ix].toString());
cmp = cmp.thenComparing(next);
}
return list.stream().sorted(cmp).collect(Collectors.toList());
}
这允许任意数量的排序标准,第一个是主要顺序,第二个是次要顺序,依此类推。
关于java - 按枚举值或字符串值对列表中的元素进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48166429/
我是一名优秀的程序员,十分优秀!