169

我有简单的课

public class ActiveAlarm {
    public long timeStarted;
    public long timeEnded;
    private String name = "";
    private String description = "";
    private String event;
    private boolean live = false;
}

List<ActiveAlarm>骗局。如何按升序排序timeStarted,然后按timeEnded?有人可以帮忙吗?我知道在 C++ 中使用通用算法和重载运算符 <,但我是 Java 新手。

4

16 回答 16

147

要么ActiveAlarm实现,要么在单独的类中Comparable<ActiveAlarm>实现。Comparator<ActiveAlarm>然后调用:

Collections.sort(list);

或者

Collections.sort(list, comparator);

一般来说,Comparable<T>如果有一个单一的“自然”排序顺序,那么实现是一个好主意......否则(如果您碰巧想要按特定顺序排序,但可能同样容易想要不同的顺序)最好实现Comparator<T>. 老实说,这种特殊情况可能会发生任何一种情况......但我可能会坚持使用更灵活的Comparator<T>选择。

编辑:示例实现:

public class AlarmByTimesComparer implements Comparator<ActiveAlarm> {
  @Override
  public int compare(ActiveAlarm x, ActiveAlarm y) {
    // TODO: Handle null x or y values
    int startComparison = compare(x.timeStarted, y.timeStarted);
    return startComparison != 0 ? startComparison
                                : compare(x.timeEnded, y.timeEnded);
  }

  // I don't know why this isn't in Long...
  private static int compare(long a, long b) {
    return a < b ? -1
         : a > b ? 1
         : 0;
  }
}
于 2011-04-27T14:21:03.997 回答
142

使用Comparator

例如:

class Score {

    private String name;
    private List<Integer> scores;
    // +accessor methods
}

    Collections.sort(scores, new Comparator<Score>() {

        public int compare(Score o1, Score o2) {
            // compare two instance of `Score` and return `int` as result.
            return o2.getScores().get(0).compareTo(o1.getScores().get(0));
        }
    });

从 Java 8 开始,您可以简单地使用 lambda 表达式来表示 Comparator 实例。

Collections.sort(scores, (s1, s2) -> { /* compute and return int */ });
于 2011-04-27T14:20:21.910 回答
67

JAVA 8 及以上答案(使用 Lambda 表达式)

在 Java 8 中,引入了 Lambda 表达式以使这变得更加容易!您可以将其简化如下:(以您的对象为例)

Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.timeStarted-a2.timeStarted);

甚至更短:

Collections.sort(list, Comparator.comparingInt(ActiveAlarm ::getterMethod));

该语句等效于以下语句:

Collections.sort(list, new Comparator<ActiveAlarm>() {
    @Override
    public int compare(ActiveAlarm a1, ActiveAlarm a2) {
        return a1.timeStarted - a2.timeStarted;
    }
});

将 Lambda 表达式视为只需要您输入代码的相关部分:方法签名和返回的内容。

您问题的另一部分是如何与多个字段进行比较。要使用 Lambda 表达式做到这一点,您可以使用该.thenComparing()函数有效地将两个比较合并为一个:

Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.timeStarted-a2.timeStarted             
       .thenComparing ((ActiveAlarm a1, ActiveAlarm a2) -> a1.timeEnded-a2.timeEnded)
);

上面的代码将首先按 对列表进行排序timeStarted,然后按timeEnded(对于那些具有相同 的记录timeStarted)。

最后一点:比较“long”或“int”原语很容易,你可以从另一个中减去一个。如果您要比较对象(“Long”或“String”),我建议您使用它们的内置比较。例子:

Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.name.compareTo(a2.name) );

编辑:感谢 Lukas Eder 指出我的.thenComparing()功能。

于 2016-03-04T20:57:17.073 回答
20

我们可以通过以下两种方式之一对列表进行排序:

1.使用比较器:当需要在多个地方使用排序逻辑如果你想在一个地方使用排序逻辑,那么你可以写一个匿名内部类如下,或者提取比较器并在多个地方使用它

  Collections.sort(arrayList, new Comparator<ActiveAlarm>() {
        public int compare(ActiveAlarm o1, ActiveAlarm o2) {
            //Sorts by 'TimeStarted' property
            return o1.getTimeStarted()<o2.getTimeStarted()?-1:o1.getTimeStarted()>o2.getTimeStarted()?1:doSecodaryOrderSort(o1,o2);
        }

        //If 'TimeStarted' property is equal sorts by 'TimeEnded' property
        public int doSecodaryOrderSort(ActiveAlarm o1,ActiveAlarm o2) {
            return o1.getTimeEnded()<o2.getTimeEnded()?-1:o1.getTimeEnded()>o2.getTimeEnded()?1:0;
        }
    });

如果我们可以使用“Long”而不是“long”,我们可以对属性进行空检查。

2. 使用 Comparable(自然排序):如果排序算法始终坚持一个属性:编写一个实现“Comparable”的类并覆盖“compareTo”方法,如下定义

class ActiveAlarm implements Comparable<ActiveAlarm>{

public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;

public ActiveAlarm(long timeStarted,long timeEnded) {
    this.timeStarted=timeStarted;
    this.timeEnded=timeEnded;
}

public long getTimeStarted() {
    return timeStarted;
}

public long getTimeEnded() {
    return timeEnded;
}

public int compareTo(ActiveAlarm o) {
    return timeStarted<o.getTimeStarted()?-1:timeStarted>o.getTimeStarted()?1:doSecodaryOrderSort(o);
}

public int doSecodaryOrderSort(ActiveAlarm o) {
    return timeEnded<o.getTimeEnded()?-1:timeEnded>o.getTimeEnded()?1:0;
}

}

调用 sort 方法进行基于自然排序的排序

Collections.sort(list);
于 2012-08-21T12:17:36.600 回答
12

在 java8+ 中,这可以写成一行,如下所示:

collectionObjec.sort(comparator_lamda)或者comparator.comparing(CollectionType::getterOfProperty)

代码:

ListOfActiveAlarmObj.sort((a,b->a.getTimeStarted().compareTo(b.getTimeStarted())))
 

或者

ListOfActiveAlarmObj.sort(Comparator.comparing(ActiveAlarm::getTimeStarted))
于 2018-04-02T06:10:42.770 回答
6
public class ActiveAlarm implements Comparable<ActiveAlarm> {
    public long timeStarted;
    public long timeEnded;
    private String name = "";
    private String description = "";
    private String event;
    private boolean live = false;

    public int compareTo(ActiveAlarm a) {
        if ( this.timeStarted > a.timeStarted )
            return 1;
        else if ( this.timeStarted < a.timeStarted )
            return -1;
        else {
             if ( this.timeEnded > a.timeEnded )
                 return 1;
             else
                 return -1;
        }
 }

这应该给你一个粗略的想法。完成后,您可以Collections.sort()在列表中调用。

于 2011-04-27T14:25:07.573 回答
5

从 Java8 开始,这可以通过结合使用ComparatorLambda expressions

例如:

class Student{

    private String name;
    private List<Score> scores;

    // +accessor methods
}

class Score {

    private int grade;
    // +accessor methods
}

    Collections.sort(student.getScores(), Comparator.comparing(Score::getGrade);
于 2017-05-04T09:09:17.903 回答
2

Guava 的比较链:

Collections.sort(list, new Comparator<ActiveAlarm>(){
            @Override
            public int compare(ActiveAlarm a1, ActiveAlarm a2) {
                 return ComparisonChain.start()
                       .compare(a1.timestarted, a2.timestarted)
                       //...
                       .compare(a1.timeEnded, a1.timeEnded).result();
            }});
于 2011-04-27T14:23:50.303 回答
2

员工 POJO 类

package in.ac.adit.oop.sort;

public class Employee {
    private int id;
    private String name;
    private String department;

    public int getId() {
        return id;
    }

    public Employee() {
        super();
    }

    public Employee(int id, String name, String department) {
        super();
        this.id = id;
        this.name = name;
        this.department = department;
    }

    @Override
    public String toString() {
        return "Employee [id=" + id + ", name=" + name + ", department=" + department + "]";
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDepartment() {
        return department;
    }

    public void setDepartment(String department) {
        this.department = department;
    }
}

员工类管理员工

package in.ac.adit.oop.sort;

import java.util.ArrayList;
import java.util.List;

    public class Example {
        public static void main(String[] args) {
    
            /*
             * Create 10 Employee Object
             */
            Employee emp1 = new Employee(1, "Nayan", "IT");
            Employee emp2 = new Employee(2, "Siddarth", "CP");
            Employee emp3 = new Employee(3, "Samarth", "AE");
            Employee emp4 = new Employee(4, "Bhavesh", "CV");
            Employee emp5 = new Employee(5, "Sam", "FT");
            Employee emp6 = new Employee(6, "Keyur", "IT");
            Employee emp7 = new Employee(7, "Bala", "ME");
            Employee emp8 = new Employee(8, "Mitul", "ME");
            Employee emp9 = new Employee(9, "Kamlesh", "EE");
            Employee emp10 = new Employee(10, "Piyush", "EE");
    
            /*
             * List of Employee Object
             */
            List<Employee> employeeList = new ArrayList<Employee>();
            employeeList.add(emp1);
            employeeList.add(emp2);
            employeeList.add(emp3);
            employeeList.add(emp4);
            employeeList.add(emp5);
            employeeList.add(emp6);
            employeeList.add(emp7);
            employeeList.add(emp8);
            employeeList.add(emp9);
            employeeList.add(emp10);
    
            CustomObjectSort customObjectSort = new CustomObjectSort();
            List<Employee> sortByDepartment = customObjectSort.sortByDepartment(employeeList);
    
            /*
             * Sorted By Department
             */
            for (Employee employee : sortByDepartment) {
                System.out.println(employee);
            }
    
            /*
             * Sorted By Name
             */
            List<Employee> sortByName = customObjectSort.sortByName(employeeList);
    
            for (Employee employee : sortByName) {
                System.out.println(employee);
            }
    
            /*
             * Sorted By Id
             */
            List<Employee> sortById = customObjectSort.sortById(employeeList);
    
            for (Employee employee : sortById) {
                System.out.println(employee);
            }
    
        }
    }

自定义排序

package in.ac.adit.oop.sort;


import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class CustomObjectSort {

    public List<Employee> sortByName(List<Employee> employeeList) {

        Collections.sort(employeeList, new Comparator<Employee>() {

            @Override
            public int compare(Employee employee1, Employee employee2) {
                return employee1.getName().compareTo(employee2.getName());
            }

        });
        return employeeList;
    }

    public List<Employee> sortByDepartment(List<Employee> employeeList) {

        Collections.sort(employeeList, new Comparator<Employee>() {

            @Override
            public int compare(Employee employee1, Employee employee2) {
                return employee1.getDepartment().compareTo(employee2.getDepartment());
            }

        });
        return employeeList;
    }

    public List<Employee> sortById(List<Employee> employeeList) {

        Collections.sort(employeeList, new Comparator<Employee>() {

            @Override
            public int compare(Employee employee1, Employee employee2) {
                return employee1.getId() - employee2.getId();
            }

        });
        return employeeList;
    }

}
于 2021-04-19T05:39:42.477 回答
2

使用Stream API的 Java-8 解决方案:

A. whentimeStartedtimeEndedare public(如要求中所述)因此不(需要)有publicgetter 方法:

List<ActiveAlarm> sorted = 
    list.stream()
        .sorted(Comparator.comparingLong((ActiveAlarm alarm) -> alarm.timeStarted)
                        .thenComparingLong((ActiveAlarm alarm) -> alarm.timeEnded))
        .collect(Collectors.toList());

B.何时timeStarted拥有getter 方法timeEndedpublic

List<ActiveAlarm> sorted = 
    list.stream()
        .sorted(Comparator.comparingLong(ActiveAlarm::getTimeStarted)
                        .thenComparingLong(ActiveAlarm::getTimeEnded))
        .collect(Collectors.toList());

如果要对原件list本身进行排序:

A. whentimeStartedtimeEndedare public(如要求中所述)因此不(需要)有publicgetter 方法:

list.sort(Comparator.comparingLong((ActiveAlarm alarm) -> alarm.timeStarted)
                    .thenComparingLong((ActiveAlarm alarm) -> alarm.timeEnded));

B.何时timeStarted拥有getter 方法timeEndedpublic

list.sort(Comparator.comparingLong(ActiveAlarm::getTimeStarted)
                    .thenComparingLong(ActiveAlarm::getTimeEnded));
于 2020-12-29T07:42:08.873 回答
1

你可以使用Collections.sort和传递你自己的Comparator<ActiveAlarm>

于 2011-04-27T14:21:50.113 回答
1

在java中,您需要使用静态Collections.sort方法。这是 CompanyRole 对象列表的示例,首先按开始排序,然后按结束排序。您可以轻松适应自己的对象。

private static void order(List<TextComponent> roles) {

    Collections.sort(roles, new Comparator() {
        @Override
        public int compare(Object o1, Object o2) {
            int x1 = ((CompanyRole) o1).getBegin();
            int x2 = ((CompanyRole) o2).getBegin();

            if (x1 != x2) {
                return x1 - x2;
            } else {
                int y1 = ((CompanyRole) o1).getEnd();
                int y2 = ((CompanyRole) o2).getEnd();
                return y2 - y1;
            }
        }
    });
}
于 2011-04-27T14:24:25.400 回答
1

我们可以使用该Comparator.comparing()方法根据对象的属性对列表进行排序。

class SortTest{
    public static void main(String[] args) {
        ArrayList<ActiveAlarm> activeAlarms = new ArrayList<>(){{
            add(new ActiveAlarm("Alarm 1", 5, 10));
            add(new ActiveAlarm("Alarm 2", 2, 12));
            add(new ActiveAlarm("Alarm 3", 0, 8));
        }};

        /* I sort the arraylist here using the getter methods */
        activeAlarms.sort(Comparator.comparing(ActiveAlarm::getTimeStarted)
                .thenComparing(ActiveAlarm::getTimeEnded));

        System.out.println(activeAlarms);
    }
}

请注意,在执行此操作之前,您必须至少定义要作为排序依据的属性的 getter 方法。

public class ActiveAlarm {
    public long timeStarted;
    public long timeEnded;
    private String name = "";
    private String description = "";
    private String event;
    private boolean live = false;

    public ActiveAlarm(String name, long timeStarted, long timeEnded) {
        this.name = name;
        this.timeStarted = timeStarted;
        this.timeEnded = timeEnded;
    }

    public long getTimeStarted() {
        return timeStarted;
    }

    public long getTimeEnded() {
        return timeEnded;
    }

    @Override
    public String toString() {
        return name;
    }
}

输出:

[Alarm 3, Alarm 2, Alarm 1]
于 2021-01-29T19:29:15.323 回答
0

您可以调用 Collections.sort() 并传入一个 Comparator ,您需要编写它来比较对象的不同属性。

于 2011-04-27T14:21:02.307 回答
0

如前所述,您可以按以下方式排序:

  • 使您的对象实现Comparable
  • 或传递ComparatorCollections.sort

如果你两者都做,Comparable将被忽略并被Comparator使用。这有助于值对象有自己的逻辑 Comparable,这对您的值对象来说是最合理的排序,而每个单独的用例都有自己的实现。

于 2016-02-29T05:52:24.153 回答
-1

在 Java(Java 8 及更高版本)中对任何对象列表进行排序的最佳和最简单的方法。让我们根据属性“fruitName”对一篮子水果进行排序

水果POJO:

class Fruit
{
    int price;
    String fruitName;
    
    
    public Fruit(int price, String fruitName) {
        super();
        this.price = price;
        this.fruitName = fruitName;
    }


    public int getPrice() {
        return price;
    }


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


    public String getFruitName() {
        return fruitName;
    }


    public void setFruitName(String fruitName) {
        this.fruitName = fruitName;
    }


    @Override
    public String toString() {
        return "Fruits [price=" + price + ", fruitName=" + fruitName + "]";
    }
    
}

现在让我们将水果添加到列表中,然后对其进行排序

List<Fruit> basketOfFruits = new ArrayList<>();
        basketOfFruits.add(new Fruit(123, "oranges"));
        basketOfFruits.add(new Fruit(45, "nectarine"));
        basketOfFruits.add(new Fruit(369, "blueberries"));
        basketOfFruits.add(new Fruit(248, "apple"));
        basketOfFruits.add(new Fruit(968, "peaches"));
        basketOfFruits.add(new Fruit(436, "grapes"));
        basketOfFruits.add(new Fruit(596, "figs"));
        
       //sorting by the property fruitName
        Collections.sort(basketOfFruits, (f1, f2)->{return f1.getFruitName().compareTo(f2.getFruitName());}); 

您现在可以打印列表(即 basketOfFruits),列表中的水果将按 ASCENDING 顺序(按字典顺序)排序。输出将如下所示:

[Fruits [price=248, fruitName=apple], Fruits [price=369, fruitName=blueberries], Fruits [price=596, fruitName=figs], Fruits [price=436, fruitName=grapes], Fruits [price=45, fruitName=nectarine], Fruits [price=123, fruitName=oranges], Fruits [price=968, fruitName=peaches]]

除了 Collections.sort(),还可以使用 Java 流(Java 8 及更高版本)。以下是使用Java流的代码

List<Fruit> sortedFruits = basketOfFruits.stream().sorted( (f1, f2)->{return f1.getFruitName().compareTo(f2.getFruitName());}).collect(Collectors.toList());

这里列表的排序方式与 Collections.sort() 相同,但排序后的项目将存储/收集在另一个列表“sortedFruits”中。所以,如果我们想打印列表的排序项,在这种情况下我们需要打印“sortedFruits”而不是“basketOfFruits”

于 2021-09-08T06:50:39.120 回答