記一個Java問題
阿新 • • 發佈:2021-06-22
一個線上閱讀網站,有若干書籍,每本書籍有若干章節,每個章節有若干字數,假設線上十萬使用者閱讀。
1. 使用者可隨時查詢任何一本書的當前閱讀使用者數;
2. 使用者可以隨時查詢任何一個章節的當前閱讀使用者數;
3. 管理員可以隨時查詢所有使用者的大概閱讀字數。
以下是我的解答,請網友們勘正:
1. 使用者類:
import java.io.Serializable; import java.util.Objects; public class User implements Serializable { private static final long serialVersionUID = 5034080277810208601L;private String name; public User(String name) { Objects.requireNonNull(name, "name can't be null."); this.setName(name); } @Override public int hashCode() { int result = 17; result = 31 * result + (name == null ? 0 : name.hashCode()); return result; } @Overridepublic boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (obj instanceof User) { User model = (User) obj; if (Objects.equals(this.getName(), model.getName())) {return true; } } return false; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
2. 圖書和章節類
import java.io.Serializable; import java.util.LinkedList; import java.util.List; import java.util.Objects; public class Book implements Serializable { private static final long serialVersionUID = 6291337232685852509L; private String name; private List<Chapter> chapters = new LinkedList<>(); public Book(String name) { Objects.requireNonNull(name, "name can't be null."); this.setName(name); } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public int hashCode() { int result = 17; result = 31 * result + (name == null ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (obj instanceof Book) { Book model = (Book) obj; if (!Objects.equals(this.getName(), model.getName())) { return false; } if (this.getChapters().size() != model.getChapters().size()) { return false; } for (int i = 0; i < this.getChapters().size(); i++) { if (!Objects.equals(this.getChapters().get(i), model.getChapters().get(i))) { return false; } } return true; } return false; } public List<Chapter> getChapters() { return chapters; } public void setChapters(List<Chapter> chapters) { this.chapters = chapters; } public void addChapter(Chapter chapter) { this.chapters.add(chapter); } public static class Chapter implements Serializable { private static final long serialVersionUID = 6374103860999522235L; private Book book; private String name; private int wordCount; public Chapter(Book book, String name, int wordCount) { Objects.requireNonNull(book, "book can't be null."); Objects.requireNonNull(name, "name can't be null."); this.setBook(book); this.setName(name); if (wordCount < 1) { throw new IllegalArgumentException("Illegal value for wordCount which must exceed 0."); } this.setWordCount(wordCount); } @Override public int hashCode() { int result = 17; result = 31 * result + (name == null ? 0 : name.hashCode()); result = 31 * result + wordCount; return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (obj instanceof Chapter) { Chapter model = (Chapter) obj; if (Objects.equals(this.getName(), model.getName()) && this.getWordCount() == model.getWordCount()) { return true; } } return false; } public Book getBook() { return book; } public void setBook(Book book) { this.book = book; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getWordCount() { return wordCount; } public void setWordCount(int wordCount) { this.wordCount = wordCount; } } }
3. 讀物統計類:
import java.util.LinkedHashMap; import java.util.concurrent.atomic.AtomicInteger; public class ReadingMaterialStatistic<R> extends LinkedHashMap<R, AtomicInteger> { private static final long serialVersionUID = -8772739941097264921L; public void read(R readingMaterial, R lastReadingMaterial) { if (readingMaterial.equals(lastReadingMaterial)) { return; } finish(lastReadingMaterial); read(readingMaterial); } private synchronized void read(R readingMaterial) { AtomicInteger counter = super.get(readingMaterial); if (counter == null) { counter = new AtomicInteger(); super.put(readingMaterial, counter); } counter.incrementAndGet(); } private void finish(R readingMaterial) { if (readingMaterial == null) { return; } super.get(readingMaterial).addAndGet(-1); } }
4. 讀者統計類:
import java.util.LinkedHashMap; public class ReaderStatistic<C extends Book.Chapter, U extends User> extends LinkedHashMap<U, C> { private static final long serialVersionUID = -6365084760182051147L; /** * Word count that reader already has been read. */ private volatile int wordCount; public synchronized C read(U user, C chapter) { wordCount += chapter.getWordCount(); return this.put(user, chapter); } public int getWordCount() { return wordCount; } }
5. 總處理類
import java.util.concurrent.atomic.AtomicInteger; import core.web.commercialalibaba.Book.Chapter; public class ReadHandler { private ReadingMaterialStatistic<Book> bookStatistic = new ReadingMaterialStatistic<>(); private ReadingMaterialStatistic<Book.Chapter> chapterStatistic = new ReadingMaterialStatistic<>(); private ReaderStatistic<Book.Chapter, User> readerStatistic = new ReaderStatistic<>(); /** * Read api */ public void read(User user, Chapter chapter) { Chapter lastChapter = readerStatistic.read(user, chapter); Book lastBook = null; if (lastChapter != null) { lastBook = lastChapter.getBook(); } bookStatistic.read(chapter.getBook(), lastBook); chapterStatistic.read(chapter, lastChapter); } /** * Reader count for specific book. */ public int readerCount4Book(Book book) { AtomicInteger counter = bookStatistic.get(book); if (counter == null) { return 0; } return counter.get(); } /** * Reader count for specific chapter. */ public int readerCount4Chapter(Book.Chapter chapter) { AtomicInteger counter = chapterStatistic.get(chapter); if (counter == null) { return 0; } return counter.get(); } /** * All read word count */ public int readWordCount() { return readerStatistic.getWordCount(); } }