用户定义对象的优先队列
Posted
技术标签:
【中文标题】用户定义对象的优先队列【英文标题】:Priority Queue of user defined objects 【发布时间】:2021-06-29 11:42:32 【问题描述】:我想根据对象的属性创建对象的优先级队列。如何根据特定属性比较队列。例如,如果我在某处输入 id,则队列是为 id 设计的。我在下面有两个不同的 java 文件。我想通过比较对象的属性来获得所有可能的队列。
第一
public class customers
int id;
String name;
int age;
double money;
public customers(int id, String name, int age, double money)
this.id = id;
this.name = name;
this.age = age;
this.money = money;
public int getId()
return id;
public void setId(int id)
this.id = id;
主文件现在开始
import java.util.ArrayList;
import java.util.PriorityQueue;
public class draft
public static void main(String[] args)
PriorityQueue<customers> customerList= new PriorityQueue<>();
customers customer1= new customers(0,"jack",30,180.5);
customers customer2= new customers(1,"john",52,800.3);
customers customer3= new customers(2,"alice", 41, 400.5);
customerList.add(customer1);
customerList.add(customer2);
customerList.add(customer3);
for (customers c:customerList
)
System.out.println(c.getId());
我想要一个像这样的简单解决方案。下面的代码无效,但我无法理解复杂的代码。我认为必须有一个简单的解决方案。
PriorityQueue<customers> customerList= new PriorityQueue<>(customers.age);
我不知道我是否解释了这个问题。例如,如果我比较对象 ID,则队列应按此顺序为对象#0、对象#1、对象#2。如果我比较对象的年龄,队列将是对象#0、对象#2、对象#1
【问题讨论】:
你可以使用 Comparator 来定义你的方法 我如何使用它,您可以输入解决方案。复杂吗? 【参考方案1】:这里有几种方法可以根据特定类的任何字段来维护 PriorityQueue
。
下图是定义一个PriorityQueue
,按照id字段排序(升序排列):
public static void main(String[] args)
// Method 1] Using Custom Comparator
PriorityQueue<Customers> pq1 = new PriorityQueue<Customers>(Comparator.comparing(Customers::getId));
Customers customer1 = new Customers(0,"jack",30,180.5);
Customers customer2 = new Customers(1,"john",52,800.3);
Customers customer3 = new Customers(2,"alice", 41, 400.5);
pq1.add(customer1);
pq1.add(customer2);
pq1.add(customer3);
// Method 2] Using Lambda Operator
PriorityQueue<Customers> pq2 = new PriorityQueue<>((x, y) -> x.id-y.id);
//Method 3] Custom Comparator again
PriorityQueue<Customers> pq3 = new PriorityQueue<>(new Comparator<Customers>()
@Override
public int compare(Customers a, Customers b)
return a.id-b.id;
);
pq2.addAll(pq1);
pq3.addAll(pq1);
System.out.println(pq1);
System.out.println(pq2);
System.out.println(pq3);
输出:[(0 , jack , 30 , 180.5), (1 , john , 52 , 800.3), (2 , alice , 41 , 400.5)]
[(0 , jack , 30 , 180.5), (1 , john , 52 , 800.3), (2 , alice , 41 , 400.5)]
[(0 , jack , 30 , 180.5), (1 , john , 52 , 800.3), (2 , alice , 41 , 400.5)]
同样,您可以根据您选择的任何字段设计其他队列。
为了以相反的顺序(递减/递减顺序)维护优先级队列,我们需要颠倒比较器中的顺序,例如:
PriorityQueue<Customers> pq2 = new PriorityQueue<>((x, y) -> y.id-x.id);
请注意,升序是:(x, y) -> x.id-y.id
对于降序,它将是:(x, y) -> y.id-x.id
使用custom Comparator
:
PriorityQueue<Customers> pq3 = new PriorityQueue<>(new Comparator<Customers>()
@Override
public int compare(Customers a, Customers b)
return b.id-a.id; // reversed
);
如果您想根据两个字段对优先级队列进行排序,假设age
和id
这样如果多个age
是相等,那么优先级已发送给id
。
您可以通过以下方式实现上述目标:
public static void main(String[] args)
// Method 1] Using Custom Comparator (Increasing order)
PriorityQueue<Customers> pq1 = new PriorityQueue<Customers>(Comparator.comparing(Customers::getAge).thenComparing(Customers::getId));
Customers customer1 = new Customers(0,"jack",30,180.5);
Customers customer2 = new Customers(1,"john",52,800.3);
Customers customer3 = new Customers(2,"alice", 41, 400.5);
pq1.add(customer1);
pq1.add(customer2);
pq1.add(customer3);
// Method 2] Using Lambda Operator (Increasing order)
PriorityQueue<Customers> pq2 = new PriorityQueue<>((x, y) -> (x.age == y.age) ? x.id-y.id : x.age-y.age);
//Method 3] Custom Comparator again (Reverse order)
PriorityQueue<Customers> pq3 = new PriorityQueue<>(new Comparator<Customers>()
@Override
public int compare(Customers a, Customers b)
return (a.age == b.age) ? b.id-a.id : b.age-a.age;
);
pq2.addAll(pq1);
pq3.addAll(pq1);
System.out.println(pq1);
System.out.println(pq2);
System.out.println(pq3);
对于基于age
和money
的排序,只需少量修改,因为money
是double 数据类型。以下是您如何实现预期目标:
PriorityQueue<Customers> pq1 = new PriorityQueue<Customers>(Comparator.comparing(Customers::getAge).thenComparing(Customers::getMoney));
PriorityQueue<Customers> pq2 = new PriorityQueue<>((x, y) -> (x.age == y.age) ? Double.compare(x.money,y.money) : x.age-y.age);
PriorityQueue<Customers> pq3 = new PriorityQueue<>(new Comparator<Customers>()
@Override
public int compare(Customers a, Customers b)
return (a.age == b.age) ? Double.compare(a.money,b.money) : a.age-b.age;
);
使用poll
方法验证priorityQueue
中元素的顺序。
所有的实现都很容易理解。但是,如果您很难理解它,请与我们联系。
【讨论】:
如何让它反转?例如,如果我想根据 id 的值创建优先级队列,从大到小。有什么实用的方法吗 我还有一个问题。如果我按年龄比较,但如果他们的年龄相等,按金钱比较,我该怎么办。我该怎么做呢 @Tarık 我已经在我的答案中添加了上述两个查询的答案。看一看。如果有帮助,请接受答案。 非常感谢。我真的很感激。您的回答非常清楚且非常有用。【参考方案2】:这样做的方法是使用多个比较器类。 Comparator 为我们提供了一种方法来定义我们希望我们的对象如何相互比较 - 在您的情况下,它可以是 id、age 等。
public class Comparator<Customer> CustomerAgeComparator implements Comparator<Customer>()
public int compare(Customer user1, Customer user2)
int userPoints1 = user1.getAge();
int userPoints2 = user2.getAge();
if (userPoints1 == userPoints2)
return 0;
else if (userPoints1 > userPoints2)
return 1;
else
return -1;
;
上述比较器将按年龄降序对客户进行排序。 然后您需要以某种方式将此信息传递给您的优先队列。幸运的是,PriorityQueue 有一个构造函数可以做到这一点。调用方式如下:
PriorityQueue oldestCustomerFirst = PriorityQueue<String>(new CustomerAgeComparator);
【讨论】:
以上是关于用户定义对象的优先队列的主要内容,如果未能解决你的问题,请参考以下文章