zoukankan      html  css  js  c++  java
  • Java 小样例:图书馆课程设计(Java 8 版)

    用 Java 模拟一个图书馆。包含创建图书、创建读者、借书、还书、列出全部图书、列出全部读者、列出已借出的图书、列出过期未还的图书等功能。

    每一个读者最多仅仅能借 3 本书,每一个书最多仅仅能借 3 个星期,超过就算过期。

    这个样例跟 http://blog.csdn.net/yidinghe/article/details/3940437 相比,添加了 Java 8 特有的语法,包含:Lambda 表达式,java.time 日期 API,streaming API 等。功能也比前者略微完好了些。体积有所减小。

    import java.time.LocalDate;
    import java.time.format.DateTimeFormatter;
    import java.time.temporal.ChronoUnit;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Scanner;
    import java.util.concurrent.atomic.AtomicInteger;
    import java.util.function.Supplier;
    import java.util.stream.Collectors;
    
    /**
     * 图书馆样例 Java 8 版本号
     * created at 2014/11/4
     *
     * @author Yiding
     */
    public class LibraryManager {
    
        public static final Scanner SCANNER = new Scanner(System.in);
    
        public static final String NUMBERS_ONLY = "^\d+$"; // 表示仅仅同意输入数字
    
        public static final String ANY_CONTENT = "^\S+$";  // 表示能够输入不论什么内容
    
        public static void main(String[] args) {
            new LibraryManager().start();
        }
    
        ////////////////////////////////////////////////////////////////
    
        private Library library = new Library();
    
        private ArrayList<Command> commands = new ArrayList<>();
    
        private String mainMenu;
    
        /**
         * 构造方法
         */
        public LibraryManager() {
            initCommands();
            initStudents();
            initBooks();
        }
    
        private void initBooks() {
            this.library.addBook("论程序猿的自我修养", "带鱼", BookType.科学类.toString());
            this.library.addBook("印度四大名著全集", "阿达木", BookType.文学类.toString());
            this.library.addBook("睡眠的优点", "程序猿阿迪", BookType.科学类.toString());
            this.library.addBook("架构师2014年10月刊", "漂亮女人网", BookType.杂志.toString());
        }
    
        private void initStudents() {
            this.library.students.add(new Student("张三"));
            this.library.students.add(new Student("李四"));
            this.library.students.add(new Student("王五"));
        }
    
        /**
         * 初始化命令和主菜单
         */
        private void initCommands() {
            addCommand(new ListCommand<>("全部图书:", () -> library.books), "查询全部图书");
            addCommand(new ListCommand<>("全部学生:", () -> library.students), "查询全部学生");
            addCommand(new AddBookCommand(), "加入图书");
            addCommand(new DeleteBookCommand(), "删除图书");
            addCommand(new BorrowBookCommand(), "借阅图书");
            addCommand(new ReturnBookCommand(), "归还图书");
            addCommand(new ListCommand<>("全部借阅过期的图书:", library::expiredBooks), "查询借阅过期的图书");
            addCommand(new ExitCommand(), "退出");
    
            this.mainMenu = toMenu("请输入命令", this.commands);
        }
    
        private void addCommand(Command command, String title) {
            command.title = title;
            this.commands.add(command);
        }
    
        /**
         * 開始运行交互
         */
        private void start() {
            CommandResult result;
    
            // 在 while 条件中推断命令的运行结果是否表示要退出程序
            // 仅仅有 ExitCommand 的运行结果是 CommandResult.EXIT
            do {
    
                try {
                    String command = prompt(mainMenu, NUMBERS_ONLY); // 选择命令
                    result = executeCommand(command);                // 运行命令
                } catch (CommandCancelException e) {
                    result = CommandResult.FAIL;
                }
    
                System.out.println(result.prompt + "
    ");
            } while (result != CommandResult.EXIT);
        }
    
        /**
         * 打印一条提示消息并返回用户的输入
         *
         * @param prompt  提示消息
         * @param pattern 指定格式,假设用户的输入不符合格式则会重复提示又一次输入。为空则不检查用户输入
         *
         * @return 用户的输入
         */
        private String prompt(String prompt, String pattern) {
            String userInput;
    
            // 在 while 条件中推断用户输入的内容是否符合 pattern 指定的格式
            // 假设 pattern 为 null 则不做推断
            do {
                System.out.print(prompt);
                userInput = SCANNER.nextLine();
    
                // 用户直接回车时,表示取消命令运行
                if (userInput.equals("")) {
                    throw new CommandCancelException();
                }
    
            } while (pattern != null && !userInput.matches(pattern));
    
            return userInput;
        }
    
        // 打印一组选项并返回用户选择的选项内容
        private String prompt(String prompt, List<?> options) {
            int index = promptIndex(prompt, options);
            return options.get(index - 1).toString();
        }
    
        // 打印一组选项并返回用户选择的位置
        private int promptIndex(String prompt, List<?

    > options) { String menu = toMenu(prompt, options); int index; do { index = Integer.parseInt(prompt(menu, NUMBERS_ONLY)); } while (index == 0 || index > options.size()); return index; } /** * 生成菜单内容 * * @param prompt 提示,在列出全部选项后打印出来 * @param options 选项 * * @return 主菜单内容 */ private <T> String toMenu(String prompt, List<T> options) { final ArrayList<String> lines = new ArrayList<>(); final AtomicInteger counter = new AtomicInteger(); options.forEach((t) -> { int index = counter.incrementAndGet(); String line = index + ": " + t.toString(); lines.add(line); }); return String.join(" ", lines) + " " + prompt + "(1-" + lines.size() + "):"; } /** * 运行用户命令 * * @param command 用户命令序号 * * @return 运行结果 */ private CommandResult executeCommand(String command) { int index = Integer.parseInt(command); if (index > 0 && index <= commands.size()) { return commands.get(index - 1).execute(); } else { return CommandResult.OK; } } //////////////////////////////////////////////////////////////// static enum CommandResult { OK("命令已完毕。"), FAIL("命令已取消。"), EXIT(""); public String prompt; // 在每一个命令结束时打印出来 CommandResult(String prompt) { this.prompt = prompt; } } static enum BookType {文学类, 科学类, 杂志} // 表示用户取消命令的异常 static class CommandCancelException extends RuntimeException { } static class Book { public static final int EXPIRE_BORROW_DAYS = 21; public String name; public String author; public String type; public String borrowedBy; public String borrowDate; Book(String name, String author, String type) { this.name = name; this.author = author; this.type = type; } public boolean isBorrowed() { return this.borrowedBy != null; } @Override public String toString() { return name + ",作者:" + author + "。" + type + (isBorrowed() ? " -- 已被'" + borrowedBy + "'于" + borrowDate + "借出" : ""); } public boolean isExpired() { if (!isBorrowed()) { return false; } // 从当前时间反推过期的借阅时间。假设实际借阅时间在过期的借阅时间之前,则表示过期了 LocalDate maxBorrowDate = LocalDate.now().minus(EXPIRE_BORROW_DAYS, ChronoUnit.DAYS); String maxBorrowDateStr = DateTimeFormatter.ofPattern("yyyyMMdd").format(maxBorrowDate); return this.borrowDate.compareTo(maxBorrowDateStr) < 0; } } static class Student { public static final int MAX_BORROW = 3; public String name; Student(String name) { this.name = name; } @Override public String toString() { return name; } } //////////////////////////////////////////////////////////////// class Library { private List<Book> books = new ArrayList<>(); private List<Student> students = new ArrayList<>(); /** * 加入书籍 * * @param bookName 书名 * @param author 作者 * @param type 类型 * * @return 运行结果 */ public CommandResult addBook(String bookName, String author, String type) { if (books.stream().anyMatch((b) -> b.name.equals(bookName))) { System.out.println("加入失败:书名已存在"); return CommandResult.FAIL; } this.books.add(new Book(bookName, author, type)); return CommandResult.OK; } public List<Book> availableBooks() { return this.books.stream().filter((b) -> !b.isBorrowed()).collect(Collectors.toList()); } public List<Book> borrowedBooks() { return this.books.stream().filter(Book::isBorrowed).collect(Collectors.toList()); } public List<Book> expiredBooks() { return this.books.stream().filter(Book::isExpired).collect(Collectors.toList()); } /** * 删除书籍 * * @param index 序号 * * @return 运行结果 */ public CommandResult deleteBook(int index) { this.books.remove(index); return CommandResult.OK; } public int countBorrowedBooks(String student) { return (int) this.books.stream().filter((b) -> student.equals(b.borrowedBy)).count(); } } //////////////////////////////////////////////////////////////// /** * 表示命令的抽象类 */ static abstract class Command { public String title; // 命令标题,将显示在主菜单中 abstract CommandResult execute(); @Override public String toString() { return title; } } // 列出满足要求的对象 class ListCommand<T> extends Command { private Supplier<List<T>> supplier; // 查询满足要求的对象的方法 private String title; // 输出标题 ListCommand(String title, Supplier<List<T>> supplier) { this.title = title; this.supplier = supplier; } @Override CommandResult execute() { System.out.println(" " + title); supplier.get().forEach(System.out::println); return CommandResult.OK; } } // 加入图书 class AddBookCommand extends Command { @Override CommandResult execute() { return library.addBook( prompt("请输入书名:", ANY_CONTENT), prompt("请输入作者:", ANY_CONTENT), prompt("请选择书籍类型:", Arrays.asList(BookType.values())) ); } } // 删除图书 class DeleteBookCommand extends Command { @Override CommandResult execute() { if (library.books.isEmpty()) { System.out.println("没有可删除的书籍。"); return CommandResult.FAIL; } int index = promptIndex("请选择书籍序号", library.books); return library.deleteBook(index - 1); } } // 借阅图书 class BorrowBookCommand extends Command { @Override CommandResult execute() { List<Book> availableBooks = library.availableBooks(); if (availableBooks.isEmpty()) { System.out.println("没有可借阅的图书。"); return CommandResult.FAIL; } int index = promptIndex("请选择要借阅的图书", availableBooks); Book book = availableBooks.get(index - 1); String student = prompt("请选择借阅者:", library.students); if (library.countBorrowedBooks(student) >= Student.MAX_BORROW) { System.out.println("该同学不能借阅很多其它图书了。"); return CommandResult.FAIL; } String bDate = prompt("请输入借阅日期(YYYYMMDD):", "^\d{8}$"); book.borrowedBy = student; book.borrowDate = bDate; return CommandResult.OK; } } // 归还图书 class ReturnBookCommand extends Command { @Override CommandResult execute() { List<Book> borrowedBooks = library.borrowedBooks(); if (borrowedBooks.isEmpty()) { System.out.println("没有图书须要归还。

    "); return CommandResult.FAIL; } int index = promptIndex("请选择已借阅的图书", borrowedBooks); Book book = borrowedBooks.get(index - 1); book.borrowedBy = null; book.borrowDate = null; System.out.println("图书已归还。"); return CommandResult.OK; } } // 退出程序 class ExitCommand extends Command { @Override CommandResult execute() { return CommandResult.EXIT; } } }



  • 相关阅读:
    centos7.6 使用yum安装mysql5.7
    解决hadoop本地库问题
    docker-compose 启动警告
    docker 安装zabbix5.0 界面乱码问题解决
    docker 部署zabbix问题
    zookeeper 超时问题
    hbase regionserver异常宕机
    (转载)hadoop 滚动升级
    hadoop Requested data length 86483783 is longer than maximum configured RPC length
    zkfc 异常退出问题,报错Received stat error from Zookeeper. code:CONNECTIONLOSS
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/5159259.html
Copyright © 2011-2022 走看看