1. 程式人生 > 其它 >記一個Java問題

記一個Java問題

一個線上閱讀網站,有若干書籍,每本書籍有若干章節,每個章節有若干字數,假設線上十萬使用者閱讀。

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; } @Override
public 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();
    }
}