Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用compareTo对对象进行排序(多种类型)_Java_Compareto - Fatal编程技术网

Java 使用compareTo对对象进行排序(多种类型)

Java 使用compareTo对对象进行排序(多种类型),java,compareto,Java,Compareto,首先,我有一个名为news article的对象,它有三个属性,我需要按它们排序: 年(整数)、月(整数)、类型(字符串-在线、纸质) 例如,它是这样的: 在线2013 4 在线2013 1 在线2009 11 在线2008 4 文件2012 12 论文2011 9 现在的情况是,月份和年份似乎排序正确,但我在按类型排序时遇到了问题。在compareTo中按字符串排序的正确方法是什么 目前的结果: 文件2012 12 论文2011 9 在线2013 4 在线2013 1 在线2009 11

首先,我有一个名为news article的对象,它有三个属性,我需要按它们排序:

年(整数)、月(整数)、类型(字符串-在线、纸质)

例如,它是这样的:

  • 在线2013 4
  • 在线2013 1
  • 在线2009 11
  • 在线2008 4
  • 文件2012 12
  • 论文2011 9
现在的情况是,月份和年份似乎排序正确,但我在按类型排序时遇到了问题。在compareTo中按字符串排序的正确方法是什么

目前的结果:

  • 文件2012 12
  • 论文2011 9
  • 在线2013 4
  • 在线2013 1
  • 在线2009 11
  • 在线2008 4
以下是我的方法(很抱歉,我的方法有些古怪,我一直在尝试不同的方法来按类型排序,并且正在试验):

我会重构(如扔掉)您的完整代码,并使用

这将创建以下代码:

enum ArticleType {
    ONLINE, PAPER
}

class Article implements Comparable<Article> {

    int year;
    int month;
    ArticleType type;

    Article(int year, int month, ArticleType type) {
        this.year = year;
        this.type = type;
        this.month = month;
    }

    @Override
    public int compareTo(Article o) {
        return new CompareToBuilder()
                .append(this.type, o.type)
                .append(this.year, o.year)
                .append(this.month, o.month)
                .toComparison();

    }

    @Override
    public String toString() {
        return Objects.toStringHelper(this)
                .add("month", month)
                .add("year", year)
                .add("type", type)
                .toString();
    }
}

@Test
public void testSortArticles() throws Exception {
    List<Article> articleList = new ArrayList<>();
    articleList.add(new Article(2012, 1, ArticleType.ONLINE));
    articleList.add(new Article(2011, 1, ArticleType.ONLINE));
    articleList.add(new Article(2011, 6, ArticleType.ONLINE));
    articleList.add(new Article(2010, 1, ArticleType.ONLINE));
    articleList.add(new Article(2010, 1, ArticleType.PAPER));
    articleList.add(new Article(2010, 2, ArticleType.PAPER));
    articleList.add(new Article(2010, 3, ArticleType.PAPER));
    articleList.add(new Article(2012, 1, ArticleType.PAPER));
    articleList.add(new Article(2012, 9, ArticleType.PAPER));

    Collections.sort(articleList);

    System.out.println(articleList);
}
Will提供了一个排序良好的列表。脱机/联机也使用枚举(ArticleType)进行排序。在我看来,这看起来比您当前的实现要好一点。

我将重构(例如扔掉)您的完整代码,并使用

这将创建以下代码:

enum ArticleType {
    ONLINE, PAPER
}

class Article implements Comparable<Article> {

    int year;
    int month;
    ArticleType type;

    Article(int year, int month, ArticleType type) {
        this.year = year;
        this.type = type;
        this.month = month;
    }

    @Override
    public int compareTo(Article o) {
        return new CompareToBuilder()
                .append(this.type, o.type)
                .append(this.year, o.year)
                .append(this.month, o.month)
                .toComparison();

    }

    @Override
    public String toString() {
        return Objects.toStringHelper(this)
                .add("month", month)
                .add("year", year)
                .add("type", type)
                .toString();
    }
}

@Test
public void testSortArticles() throws Exception {
    List<Article> articleList = new ArrayList<>();
    articleList.add(new Article(2012, 1, ArticleType.ONLINE));
    articleList.add(new Article(2011, 1, ArticleType.ONLINE));
    articleList.add(new Article(2011, 6, ArticleType.ONLINE));
    articleList.add(new Article(2010, 1, ArticleType.ONLINE));
    articleList.add(new Article(2010, 1, ArticleType.PAPER));
    articleList.add(new Article(2010, 2, ArticleType.PAPER));
    articleList.add(new Article(2010, 3, ArticleType.PAPER));
    articleList.add(new Article(2012, 1, ArticleType.PAPER));
    articleList.add(new Article(2012, 9, ArticleType.PAPER));

    Collections.sort(articleList);

    System.out.println(articleList);
}

Will提供了一个排序良好的列表。脱机/联机也使用枚举(ArticleType)进行排序。在我看来,这看起来比您当前的实现要好一点。

要回答您的问题,您只需使用
compareTo()
来比较两个
String
对象。你只需要确保按照你想要的顺序比较它们。做

x = type2.compareTo(type1);
按降序比较
字符串
s。如果要按升序排序,则需要执行以下操作

x = type1.compareTo(type2);
另外,我对所有的
==null
!=空
检查。因为这是您自己的类,所以您应该控制成员字段是否可以为
null
。如果我正在编写一个类似的类,我会要求所有字段都由构造函数初始化,这样我就不需要检查
null
值。这可以大大简化类中的所有其他方法,包括这个
compareTo()
方法

此外,您应该更喜欢内置类型而不是包装类。换句话说,对年和月字段使用
int
s,而不是
Integer
s。这还可以通过两种方式帮助简化代码。首先,您不必担心
null
值。第二,您可以通过简单的减法与
int
s进行比较:

int compareYears = this.year - rs.year;
if (compareYears != 0) {
    return compareYears;
}
有了这些建议,您不仅可以解决当前的问题,还可以将代码行数减少至少一半


(请注意,通常情况下,由于溢出,您必须小心使用减法比较
int
s。在这种情况下,由于我们比较的是年份,因此两个值都不应该为负值,因此不应该出现问题。当然,您的类的其他成员应该强制执行
year
字段实际上是有效的年份。)

要回答您的问题,您只需使用
compareTo()
来比较两个
String
对象。你只需要确保按照你想要的顺序比较它们。做

x = type2.compareTo(type1);
按降序比较
字符串
s。如果要按升序排序,则需要执行以下操作

x = type1.compareTo(type2);
另外,我对所有的
==null
!=空
检查。因为这是您自己的类,所以您应该控制成员字段是否可以为
null
。如果我正在编写一个类似的类,我会要求所有字段都由构造函数初始化,这样我就不需要检查
null
值。这可以大大简化类中的所有其他方法,包括这个
compareTo()
方法

此外,您应该更喜欢内置类型而不是包装类。换句话说,对年和月字段使用
int
s,而不是
Integer
s。这还可以通过两种方式帮助简化代码。首先,您不必担心
null
值。第二,您可以通过简单的减法与
int
s进行比较:

int compareYears = this.year - rs.year;
if (compareYears != 0) {
    return compareYears;
}
有了这些建议,您不仅可以解决当前的问题,还可以将代码行数减少至少一半


(请注意,通常情况下,由于溢出,您必须小心使用减法比较
int
s。在这种情况下,由于我们比较的是年份,因此两个值都不应该为负值,因此不应该出现问题。当然,您的类的其他成员应该强制执行
year
字段实际上是有效的年份。)

如果类型不为null,则将其替换为0,无论其值是什么。因此,将“纸质”与“在线”进行比较会导致将0与0进行比较,这显然是错误的

我的第一个建议是使用适当的类型,而不是字符串。月份和年份应为
int
s,类型应为枚举。您还应该努力使它们不可为null

一旦完成,比较方法将减少到

public int compareTo(Article other) {
    int result = this.type.compareTo(other.type);
    if (result == 0) {
        result = Integer.compare(this.year, other.year);
    }
    if (result == 0) {
        result = Integer.compare(this.month, other.month);
    }
    return result;
}
请注意,使用枚举可以指定类型比较的方式,只需按所需顺序列出值即可

或者更好,用番石榴:

public int compareTo(Article other) {
    return ComparisonChain.start()
                          .compare(this.type, other.type)
                          .compare(this.year, other.year)
                          .compare(this.month, other.month)
                          .result();
}
如果值可以为null,则必须将上述代码更改为

public int compareTo(Article other) {
    return ComparisonChain.start()
                .compare(this.type, other.type, Ordering.natural().nullsLast())
                .compare(this.year, other.year, Ordering.natural().nullsLast())
                .compare(this.month, other.month, Ordering.natural().nullsLast())
                .result();
}

如果类型不为null,则将其替换为0,无论其值是什么。因此,将“纸质”与“在线”进行比较会导致将0与0进行比较,这显然是错误的

我的第一个建议是使用适当的类型,而不是字符串。月份和年份应为
int
s,类型应为枚举。您还应该努力使它们不可为null

一旦完成,比较方法将减少到

public int compareTo(Article other) {
    int result = this.type.compareTo(other.type);
    if (result == 0) {
        result = Integer.compare(this.year, other.year);
    }
    if (result == 0) {
        result = Integer.compare(this.month, other.month);
    }
    return result;
}
请注意,使用枚举允许您口述