【问题标题】:how to implement a book ranking - JAVA如何实现图书排名 - JAVA
【发布时间】:2021-09-01 06:17:31
【问题描述】:

有人可以帮我在 JAVA 中实现一个获取书店销量最高的 50 本书的方法吗?

这是Bookstore 类:

public class Bookstore implements Serializable {

    private static final long serialVersionUID = -3099048826035606338L;
    private boolean populated;
    private final List<Country> countryById;
    private final Map<String, Country> countryByName;
    private final List<Address> addressById;
    private final Map<Address, Address> addressByAll;
    private final List<Customer> customersById;
    private final Map<String, Customer> customersByUsername;
    private final List<Author> authorsById;
    private final List<Book> booksById;
    private final List<Cart> cartsById;
    private final List<Order> ordersById;
    private final LinkedList<Order> ordersByCreation;

OrderLine 是另一个带有订单详细信息的类,例如:

    private final Book book;
    private final int qty;
    private final double discount;
    private final String comments;

我开始这样做:(我必须考虑订单状态已发货和书的主题),但我不知道这是否正确或下一步该怎么做,例如,如何将数量相加bookId 并订购 bestSellers 列表:

public List<Book> getBestSellers(String subject) {

         ArrayList<Book> bestSellers = new ArrayList<Book>();
         for (Order order : ordersById) {
             if (order.getStatus().equalsIgnoreCase("SHIPPED")) {
                 for (int i=0; i<order.getLines().size(); i++){

【问题讨论】:

  • 或许可以创建一个 Map,以 Book 对象为键,以 Integer 为值。

标签: java list sorting arraylist


【解决方案1】:

首先,您需要收集数量为一本Map&lt;Book, Integer&gt;的所有书籍。然后你应该对它们进行排序并限制为 50 个。

应该是这样的:

        List<Book> books = orders.stream().filter(PhilippBooks::isShipped)
                .flatMap(Order::lines)
                .collect(Collectors.toMap(OrderLine::getBook, OrderLine::getQuantity, Integer::sum))
                .entrySet()
                .stream()
                .sorted(PhilippBooks.reversed())
                .limit(50)
                .peek(System.out::println)
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());

并确保您的 Book 类正确实现了hashCode 函数。在地图上收集书籍是必需的。

完整代码示例:

public class PhilippBooks {

    public static void main(String[] args) {
        Book tolstoy = new Book("Tolstoy");
        Book dostoevsky = new Book("Dostoevsky");
        Book london = new Book("London");

        List<Order> orders = List.of(
                new Order("SHIPPED", new OrderLine(tolstoy, 3), new OrderLine(london, 6)),
                new Order("SHIPPED", new OrderLine(tolstoy, 2), new OrderLine(dostoevsky, 10)),
                new Order("OTHER", new OrderLine(tolstoy, 1), new OrderLine(london, 1), new OrderLine(dostoevsky, 1)));

        List<Book> books = orders.stream().filter(PhilippBooks::isShipped)
                .flatMap(Order::lines)
                .collect(Collectors.toMap(OrderLine::getBook, OrderLine::getQuantity, Integer::sum))
                .entrySet()
                .stream()
                .sorted(PhilippBooks.reversed())
                .limit(50)
                .peek(System.out::println)
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());

        System.out.println(books);
    }

    private static Comparator<Map.Entry<Book, Integer>> reversed(){
        return (o1, o2) -> o2.getValue() - o1.getValue();
    }

    private static boolean isShipped(Order order){
        return order.getStatus().equalsIgnoreCase("SHIPPED");
    }

    private static class Book {
        private final String name;

        private Book(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return "Book{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }

    private static class Order {
        private final String status;
        private final List<OrderLine> lines;

        public Order(String status, OrderLine... lines) {
            this(status, Arrays.asList(lines));
        }

        public Order(String status, List<OrderLine> lines) {
            this.status = status;
            this.lines = lines;
        }

        public Stream<OrderLine> lines(){
            return lines.stream();
        }

        public String getStatus() {
            return status;
        }
    }

    private static class OrderLine {

        private final Book book;
        private final int quantity;

        public OrderLine(Book book, int quantity) {
            this.book = book;
            this.quantity = quantity;
        }

        public Book getBook() {
            return book;
        }

        public int getQuantity() {
            return quantity;
        }
    }
}

【讨论】:

  • 感谢您的帮助!但我还有一个(我猜是最后的)问题......如果我有这样的 getBestSellers 方法实现(在下一条评论中)
  • Map mapa = new HashMap(); List bestSellers = new ArrayList(); for (Order order : ordersById) { if (order.getStatus().equalsIgnoreCase("SHIPPED")) { for (OrderLine orderLine: order.getLines()) { int qtd = 0; if (subject.equalsIgnoreCase(orderLine.getBook().getSubject())) { if (mapa.get(orderLine.getBook()) !=null) { qtd = mapa.get(orderLine.getBook()); } mapa.put(orderLine.getBook(), orderLine.getQty() + qtd);
  • 如何使用列表订购此商品并仅返回 50 个最佳卖家
  • 我在上面的例子中已经做到了:mapa.entrySet() .stream().sorted(PhilippBooks.reversed()).limit(50)
  • 然后我从排序的实体中得到列表:.map(Map.Entry::getKey).collect(Collectors.toList())
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-10
  • 1970-01-01
  • 2018-11-12
  • 1970-01-01
  • 2014-03-05
相关资源
最近更新 更多