gpt4 book ai didi

java - 按枚举值或字符串值对列表中的元素进行排序

转载 作者:行者123 更新时间:2023-12-01 07:01:19 27 4
gpt4 key购买 nike

我想通过比较字符串值或枚举值来按升序和降序对 ArrayList 进行排序。

这是我想要排序的ArrayList:

List<Issue> issues;

列表将根据我赋予函数的两个参数(fieldsort)进行排序:

private List<Issue> sortList(List<Issue> list, String field, String sort) {
// My code goes here
}

因此,我们假设 field 值为 titlesort 值为 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 实现的当前状态,并具有适当的 equalshashCode 实现:

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/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com