java 队列示例_Java中的优先级队列用示例解释

java 队列示例

Priority Queues are used very often in real life applications. In this article we will learn what priority queues are and how we can use them in Java.

优先队列在现实生活中经常使用。 在本文中,我们将学习什么是优先级队列以及如何在Java中使用它们。

Before we discuss what a priority queue is, let's see what a regular queue is.

在讨论优先级队列是什么之前,让我们看一下常规队列是什么。

A regular queue follows a first in first out ( FIFO ) structure. This means that if 3 messages – m1, m2 and m3 – go into the queue in that order, then they come out of the queue in the exact same order.

常规队列遵循先进先出(FIFO)结构。 这意味着,如果3条消息(m1,m2和m3)以该顺序进入队列,则它们以完全相同的顺序从队列中出来。

我们为什么需要队列? (Why do we need queues?)

Let us say that we have data producers ( for example, when a user clicks on a web page ) which are extremely fast. But then we want to consume this data at a slower pace later.

假设我们有非常快速的数据生成器(例如,当用户单击网页时)。 但是随后我们想以较慢的速度使用此数据。

In this case, the producer would push all of the messages into the queue, and a consumer would consume these messages later from the queue at a slower pace.

在这种情况下,生产者将所有消息推送到队列中,而消费者稍后将以较慢的速度从队列中使用这些消息。

什么是优先级队列? (What is a priority queue?)

As mentioned earlier, a regular queue has a first in first out structure. But in some scenarios we want to process messages in a queue based on their priority and not based on when the message entered the queue.

如前所述,常规队列具有先进先出结构。 但是在某些情况下,我们希望根据消息的优先级而不是根据消息进入队列的时间来处理队列中的消息。

Priority queues help consumers consume the higher priority messages first followed by the lower priority messages.

优先级队列帮助使用者先使用较高优先级的消息,然后再使用较低优先级的消息。

Java中的优先级队列 (Priority queues in Java)

Now let's see some actual Java code that will show us how to use priority queues.

现在,让我们看一些实际的Java代码,这些代码将向我们展示如何使用优先级队列。

具有自然顺序的优先队列 (Priority queues with natural ordering)

Here is some code showing how to create a simple priority queue for strings

这是一些代码,显示了如何为字符串创建简单的优先级队列

private static void testStringsNaturalOrdering() {
        Queue<String> testStringsPQ = new PriorityQueue<>();
        testStringsPQ.add("abcd");
        testStringsPQ.add("1234");
        testStringsPQ.add("23bc");
        testStringsPQ.add("zzxx");
        testStringsPQ.add("abxy");

        System.out.println("Strings Stored in Natural Ordering in a Priority Queue\n");
        while (!testStringsPQ.isEmpty()) {
            System.out.println(testStringsPQ.poll());
        }
    }

The first line tells us that we are creating a priority queue:

第一行告诉我们我们正在创建优先级队列:

Queue<String> testStringsPQ = new PriorityQueue<>();

PriorityQueue is available in java.util package.

PriorityQueue在java.util包中可用。

Next we are adding 5 strings in random order into the priority queue. For this we use the add() function as shown below:

接下来,我们将以随机顺序将5个字符串添加到优先级队列中。 为此,我们使用add()函数,如下所示:

testStringsPQ.add("abcd");
testStringsPQ.add("1234");
testStringsPQ.add("23bc");
testStringsPQ.add("zzxx");
testStringsPQ.add("abxy");

In order to get the latest item from the queue we use the poll() function as shown below:

为了从队列中获取最新的项目,我们使用poll()函数,如下所示:

testStringsPQ.poll()

poll() will give us the latest item and also remove it from the queue. If we want to get the latest item in the queue without removing it, we can use the peek() function:

poll()将为我们提供最新的项目,并将其从队列中删除。 如果我们想获取队列中的最新项目而不删除它,可以使用peek()函数:

testStringsPQ.peek()

Finally, we print out all the elements from the queue by using the poll() function as shown below:

最后,我们使用poll()函数打印出队列中的所有元素,如下所示:

while (!testStringsPQ.isEmpty()) {
   System.out.println(testStringsPQ.poll());
}

Here is the output of the above program:

这是上面程序的输出:

1234
23bc
abcd
abxy
zzxx

Since we did not tell the priority queue how to prioritize its content, it used a default natural ordering. In this case, it gave us the data back in the ascending order of the strings. This is not the same order in which items were added to the queue.

由于我们没有告诉优先级队列如何确定其内容的优先级,因此它使用了默认的自然顺序。 在这种情况下,它以字符串的升序将数据返回给我们。 这与将项目添加到队列中的顺序不同。

定制订单怎么样? (What about having a custom ordering?)

This is possible as well, and we can do it with the help of a comparator.

这也是可能的,我们可以在比较器的帮助下做到这一点

Let's create an integer priority queue now. But this time let's get the result in descending order of value.

现在创建一个整数优先级队列。 但是这次让我们以值的降序获得结果。

In order to achieve this, first we need to create an integer comparator:

为了实现这一点,首先我们需要创建一个整数比较器:

static class CustomIntegerComparator implements Comparator<Integer> {

        @Override
        public int compare(Integer o1, Integer o2) {
            return o1 < o2 ? 1 : -1;
        }
    }

In order to create a comparator, we implement the comparator interface and override the compare method.

为了创建一个比较器,我们实现了比较器接口并覆盖了compare方法。

By using o1 < o2 ? 1 : -1 we will get the result in descending order. If we had used o1 > o2 ? 1 : -1, then we would have gotten the result in ascending order

通过使用o1 <o2吗? 1:-1,我们将按降序获得结果。 如果我们使用o1> o2? 1:-1,那么我们将得到升序的结果

Now that we have the comparator, we need to add this comparator to the priority queue. We can do this like this:

现在我们有了比较器,我们需要将此比较器添加到优先级队列中。 我们可以这样做:

Queue<Integer> testIntegersPQ = new PriorityQueue<>(new CustomIntegerComparator());

Here is the rest of the code which adds elements into the priority queue and prints them:

以下是将元素添加到优先级队列并进行打印的其余代码:

testIntegersPQ.add(11);
        testIntegersPQ.add(5);
        testIntegersPQ.add(-1);
        testIntegersPQ.add(12);
        testIntegersPQ.add(6);

        System.out.println("Integers stored in reverse order of priority in a Priority Queue\n");
        while (!testIntegersPQ.isEmpty()) {
            System.out.println(testIntegersPQ.poll());
        }

The output of the above program is given below:

上面程序的输出如下:

12
11
6
5
-1

We can see that the comparator has done its job well. Now the priority queue is giving us the integers in descending order.

我们可以看到比较器做得很好。 现在,优先级队列按降序排列给我们整数。

具有Java对象的优先级队列 (Priority queue with Java objects)

Up to this point, we've seen how we can use strings and integers with priority queues.

到目前为止,我们已经了解了如何在优先级队列中使用字符串和整数。

In real life applications we would generally be using priority queues with custom Java objects.

在现实生活中的应用程序中,通常将优先级队列与自定义Java对象一起使用。

Let's first create a class called CustomerOrder which is used to store customer order details:

首先创建一个名为CustomerOrder的类,该类用于存储客户订单的详细信息:

public class CustomerOrder implements Comparable<CustomerOrder> {
    private int orderId;
    private double orderAmount;
    private String customerName;

    public CustomerOrder(int orderId, double orderAmount, String customerName) {
        this.orderId = orderId;
        this.orderAmount = orderAmount;
        this.customerName = customerName;
    }

    @Override
    public int compareTo(CustomerOrder o) {
        return o.orderId > this.orderId ? 1 : -1;
    }

    @Override
    public String toString() {
        return "orderId:" + this.orderId + ", orderAmount:" + this.orderAmount + ", customerName:" + customerName;
    }

    public double getOrderAmount() {
        return orderAmount;
    }
}

This is a simple Java class to store customer orders. This class implements comparable interface, so that we can decide on what basis this object needs to be ordered in the priority queue.

这是一个用于存储客户订单的简单Java类。 此类实现可比较的接口,以便我们可以确定需要在什么基础上在优先级队列中对该对象进行排序。

The ordering is decided by the compareTo function in the above code. The line o.orderId > this.orderId ? 1 : -1 instructs that the orders should be sorted based on descending order of the orderId field

顺序由以上代码中的compareTo函数确定。 o.orderId> this.orderId行? 1:-1指示应基于orderId字段的降序对订单进行排序

Below is the code which creates a priority queue for the CustomerOrder object:

下面是为CustomerOrder对象创建优先级队列的代码:

CustomerOrder c1 = new CustomerOrder(1, 100.0, "customer1");
CustomerOrder c2 = new CustomerOrder(3, 50.0, "customer3");
CustomerOrder c3 = new CustomerOrder(2, 300.0, "customer2");

Queue<CustomerOrder> customerOrders = new PriorityQueue<>();
customerOrders.add(c1);
customerOrders.add(c2);
customerOrders.add(c3);
while (!customerOrders.isEmpty()) {
	System.out.println(customerOrders.poll());
}

In the above code three customer orders have been created and added to the priority queue.

在上面的代码中,已经创建了三个客户订单并将其添加到优先级队列中。

When we run this code we get the following output:

运行此代码时,将得到以下输出:

orderId:3, orderAmount:50.0, customerName:customer3
orderId:2, orderAmount:300.0, customerName:customer2
orderId:1, orderAmount:100.0, customerName:customer1

As expected, the result comes in descending order of the orderId.

如预期的那样,结果按orderId的降序排列。

如果我们想基于orderAmount确定优先级怎么办? (What if we want to prioritize based on orderAmount?)

This is again a real life scenario. Let's say that by default the CustomerOrder object is prioritized by the orderId. But then we need a way in which we can prioritize based on orderAmount.

这又是现实生活中的情况。 假设默认情况下,CustomerOrder对象的优先级为orderId。 但是,然后我们需要一种可以基于orderAmount进行优先级排序的方法。

You may immediately think that we can modify the compareTo function in the CustomerOrder class to order based on orderAmount.

您可能会立即想到,我们可以将CustomerOrder类中compareTo函数修改为基于orderAmount的订单。

But the CustomerOrder class may be used in multiple places in the application, and it would interfere with the rest of the application if we modify the compareTo function directly.

但是CustomerOrder类可能会在应用程序中的多个位置使用,如果我们直接修改compareTo函数,它将干扰应用程序的其余部分。

The solution to this is pretty simple: we can create a new custom comparator for the CustomerOrder class and use that along with the priority queue

解决方案非常简单:我们可以为CustomerOrder类创建一个新的自定义比较器,并将其与优先级队列一起使用

Below is the code for the custom comparator:

以下是自定义比较器的代码:

static class CustomerOrderComparator implements Comparator<CustomerOrder> {

        @Override
        public int compare(CustomerOrder o1, CustomerOrder o2)
        {
            return o1.getOrderAmount() < o2.getOrderAmount() ? 1 : -1;
        }
    }

This is very similar to the custom integer comparator we saw earlier.

这与我们之前看到的自定义整数比较器非常相似。

The line o1.getOrderAmount() < o2.getOrderAmount() ? 1 : -1; indicates that we need to prioritize based on descending order of orderAmount.

这行o1.getOrderAmount() < o2.getOrderAmount() ? 1 : -1; o1.getOrderAmount() < o2.getOrderAmount() ? 1 : -1; 表示我们需要基于orderAmount的降序进行优先级排序

Below is the code which creates the priority queue:

以下是创建优先级队列的代码:

CustomerOrder c1 = new CustomerOrder(1, 100.0, "customer1");
        CustomerOrder c2 = new CustomerOrder(3, 50.0, "customer3");
        CustomerOrder c3 = new CustomerOrder(2, 300.0, "customer2");
        Queue<CustomerOrder> customerOrders = new PriorityQueue<>(new CustomerOrderComparator());
        customerOrders.add(c1);
        customerOrders.add(c2);
        customerOrders.add(c3);
        while (!customerOrders.isEmpty()) {
            System.out.println(customerOrders.poll());
        }

In the above code we are passing the comparator to the priority queue in the following line of code:

在上面的代码中,我们在下面的代码行中将比较器传递给优先级队列:

Queue<CustomerOrder> customerOrders = new PriorityQueue<>(new CustomerOrderComparator());

Below is the result when we run this code:

下面是我们运行此代码的结果:

orderId:2, orderAmount:300.0, customerName:customer2
orderId:1, orderAmount:100.0, customerName:customer1
orderId:3, orderAmount:50.0, customerName:customer3

We can see that the data comes in descending order of the orderAmount.

我们可以看到数据以orderAmount的降序排列。

(Code)

All the code discussed in this article can be found in this GitHub repo.

本文讨论的所有代码都可以在此GitHub存储库中找到。

恭喜😊 (Congrats 😊)

You now know how to use priority queues in Java.

您现在知道了如何在Java中使用优先级队列。

关于作者 (About the author)

I love technology and follow the advancements in the field. I also like helping others with my technology knowledge.

我热爱技术,并关注该领域的进步。 我也喜欢用我的技术知识来帮助他人。

Feel free to connect with me on my LinkedIn account https://www.linkedin.com/in/aditya1811/

随时使用我的LinkedIn帐户与我联系https://www.linkedin.com/in/aditya1811/

You can also follow me on twitter https://twitter.com/adityasridhar18

您也可以在Twitter上关注我https://twitter.com/adityasridhar18

Feel free to read more of my articles on my blog at adityasridhar.com.

随时在adityasridhar.com的博客上阅读我的更多文章

翻译自: https://www.freecodecamp.org/news/priority-queue-implementation-in-java/

java 队列示例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值