目录
基本结构:
对基本信息的封装:设计图书信息类,读者信息类,借阅信息类;
功能实现:
1.在main方法外面定义集合,分别作为读者信息表,图书信息表,借阅信息表;
2.在LibraryTest类中定义main方法,实现要求的功能;
3.对具体操作的实现分为读者功能和管理员功能;
基本信息:
基本元素类(Element):
作为图书类,用户信息类的父类,封装名字和号码。
package wryyyyy;
import java.io.Serializable;
public class Element implements Serializable
{
private String name;
private String number;
public Element(String name, String number) {
this.name = name;
this.number = number;
}
public Element() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
}
图书信息类(Book):
package wryyyyy;
import java.io.Serializable;
import java.util.*;
public class Book extends Element implements Comparable<Book>, Serializable
{
private String author;
private String press;
private String data;
private int contain;
private double price;
public Book(String name, String number, String author, String press, String data, int contain, double price) {
super(name, number);
this.author = author;
this.press = press;
this.data = data;
this.contain = contain;
this.price = price;
}
public Book() {
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getPress() {
return press;
}
public void setPress(String press) {
this.press = press;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public int getContain() {
return contain;
}
public void setContain(int contain) {
this.contain = contain;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "书名:"+this.getName()+" 书号:"+this.getNumber()+" 作者:"+author+" 出版社:"+press+
" 出版时间:"+data+" 馆存数量:"+contain+" 价格:"+price;
}
//重写hashCode?
@Override
public int compareTo(Book o)
{
for (int i = 0; i < 5; i++)
{
if (Objects.equals((int)o.getNumber().charAt(i),(int)this.getNumber().charAt(i)))
{
continue;
}
else
{
return (int)o.getNumber().charAt(i)-(int)this.getNumber().charAt(i)>0?-1:1;
}
}
return 0;
}
@Override
public boolean equals(Object o)
{
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Book book = (Book) o;
return Objects.equals(this.getName(),book.getName()) && Objects.equals(this.getNumber(),book.getNumber())
&& Objects.equals(this.author,book.author) && Objects.equals(this.press,book.press) && Objects.equals(this.data,book.data)
&& Objects.equals(this.price,book.price);
}
@Override
public int hashCode() {
return Objects.hash(this.getName(),this.getNumber(),author, press, data, contain, price);
}
}
用户信息类(User):
继承基本元素类,是读者信息类和管理员信息类的父类。封装姓名,号码,登录密码。
package wryyyyy;
import java.io.Serializable;
import java.util.Objects;
public class User extends Element implements Serializable
{
private String passWord;
public String getPassWord() {
return passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
}
public User(String name, String number, String passWord) {
super(name, number);
this.passWord = passWord;
}
public User() {
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Objects.equals(passWord, user.passWord);
}
@Override
public int hashCode() {
return Objects.hash(passWord);
}
}
读者信息类(Reader):
继承用户类,增加了读者独有属性。
package wryyyyy;
import java.io.Serializable;
import java.util.*;
public class Reader extends User implements Comparable<Reader>, Serializable
{
private String academic;
private String subject;
private String GradeAndClass;
public Reader(String name,String number,String password,String academic, String subject, String gradeAndClass)
{
super(name,number,password);
this.academic = academic;
this.subject = subject;
GradeAndClass = gradeAndClass;
}
public Reader() {
}
public String getAcademic() {
return academic;
}
public void setAcademic(String academic) {
this.academic = academic;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getGradeAndClass() {
return GradeAndClass;
}
public void setGradeAndClass(String gradeAndClass) {
GradeAndClass = gradeAndClass;
}
@Override
public String toString() {
return "姓名:"+this.getName()+" 学号:"+this.getNumber()+" 登录密码:"+this.getPassWord()
+" 学院:"+academic+" 专业:"+subject+" 班级:"+GradeAndClass;
}
@Override
public int compareTo(Reader o)
{
List<String> sizes = new ArrayList<>();
Collections.addAll(sizes,"信息学院","机械电子学院","经管学院","林学院","外国语学院","动科学院","资环学院");
if (Objects.equals(o.getAcademic(),this.getAcademic())==false)
{
return sizes.indexOf(o.getAcademic())-sizes.indexOf(this.getAcademic())>0?-1:1;
}
else if(Objects.equals(o.getNumber(),this.getNumber())==false)
{
return Integer.valueOf(o.getNumber())-Integer.valueOf(this.getNumber())>0?-1:1;
}
else
{
return 0;
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Reader reader = (Reader) o;
return Objects.equals(this.getPassWord(), reader.getPassWord()) &&Objects.equals(this.getNumber(), reader.getNumber())
&&Objects.equals(this.getName(), reader.getName()) &&Objects.equals(academic, reader.academic)
&& Objects.equals(subject, reader.subject) && Objects.equals(GradeAndClass, reader.GradeAndClass);
}
@Override
public int hashCode() {
return Objects.hash(this.getName(),this.getNumber(),this.getPassWord(),academic, subject, GradeAndClass);
}
}
管理员信息类(Manager):
继承用户类。
package wryyyyy;
import java.io.Serializable;
public class Manager extends User implements Serializable
{
public Manager(String name, String number, String passWord) {
super(name, number, passWord);
}
public Manager() {
}
@Override
public String toString()
{
return "姓名:"+this.getName()+" 工号:"+this.getNumber()+" 登录密码:"+this.getPassWord();
}
}
借阅信息类(Lend):
封装读者信息,图书信息,借出及归还时间(用字符串形式存储)。
package wryyyyy;
import java.io.Serializable;
import java.util.Objects;
public class Lend implements Serializable
{
private Book book_in_lend;
private Reader reader_in_lend;//如果出现问题就把这个改成字符串
private String time_from;//改成存储字符串,数据格式化放在借书那里
private String time_to;
public Lend(Book book_in_lend, Reader reader_in_lend, String time_from, String time_to)
{
this.book_in_lend = book_in_lend;
this.reader_in_lend = reader_in_lend;
this.time_from = time_from;
this.time_to = time_to;
}
public Lend() {
}
public Book getBook_in_lend() {
return book_in_lend;
}
public void setBook_in_lend(Book book_in_lend) {
this.book_in_lend = book_in_lend;
}
public Reader getReader_in_lend() {
return reader_in_lend;
}
public void setReader_in_lend(Reader reader_in_lend) {
this.reader_in_lend = reader_in_lend;
}
public String getTime_from() {
return time_from;
}
public void setTime_from(String time_from) {
this.time_from = time_from;
}
public String getTime_to() {
return time_to;
}
public void setTime_to(String time_to) {
this.time_to = time_to;
}
@Override
public String toString() {
return "---" +
"在借图书:" + book_in_lend.getName() +"("+book_in_lend.getNumber()+
") 读者姓名:" + reader_in_lend.getName() +" 读者学号:" + reader_in_lend.getNumber()+
" 借出时间:" + (time_from) +
" 归还时间:" + time_to ;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Lend lend = (Lend) o;
return Objects.equals(book_in_lend, lend.book_in_lend) && Objects.equals(reader_in_lend, lend.reader_in_lend) && Objects.equals(time_from, lend.time_from) ;
}
@Override
public int hashCode() {
return Objects.hash(book_in_lend, reader_in_lend, time_from);
}
}
信息表:
对于读者信息存储,既要存储读者信息,又要存储读者的借书信息,用map集合存储,value用来存储读者对应的借书信息。
对于图书信息,要区分馆存数量和现有数量,现有数量用value值存储。
//存储用户对象
public static Set<User> ALL_USERS = new HashSet<>();
//存储读者和借书信息
public static Map<Reader,Set<Lend>> READERS_BOOKS = new TreeMap<>();
//存储图书借阅信息
public static Set<Lend> ALL_IN_LEND = new HashSet<>();
//存储图书信息
操作实现:
定义LibraryTest实现具体操作;
通过调用方法实现各操作,整个系统功能的实现放在showmain()方法中;
用return结束方法调用,退出当前操作;
首页:
进入系统后可以选择登录,管理员注册,读者注册,退出系统功能。
登录功能:
1.首先在main方法外面定义一个User对象命名为loginUser,确定登录对象之后把这个对象给loginUser,由此确定是谁在使用这个系统;
2.确定登录对象后用instanceof判断对象类型,确定是进入读者页面还是管理员页面;
private static void login() throws IOException//登录
{
while (true)
{
System.out.println("请输入登录名称:");
String loginName = SYS_SC.nextLine();
System.out.println("请输入登录密码(6位数字):");
String passWord = SYS_SC.nextLine();
User u = getUserByLoginName(loginName);//确认登录对象
if(u!=null)
{
if(u.getPassWord().equals(passWord))
{
loginUser = u;
if(u instanceof Manager)
{
showManagerMain();
}
else
{
showReaderMain();
}
}
else
{
System.out.println("密码错误");
}
}
else
{
System.out.println("登录名称错误,请确认!");
}
return;//方法执行完之后,结束login回到首页(Switch那里)
}
}
查找功能:
读者信息查询,图书信息查询:
1.用增强for进行查找
2.找到一个符合条件结果之后,不能break,输出所有符合条件结果
3.采用模糊查找(contains)
以图书信息查找为例:
private static void inquireBook()//图书查询
{
System.out.println("===================查询图书信息==================");
while (true)
{
System.out.println("请输入书名/书号/作者/出版社");
String search = SYS_SC.nextLine();
Set<Book> books = ALL_BOOKS.keySet();
for (Book book : books)
{
if (book.getName().contains(search)||book.getNumber().contains(search)
||book.getAuthor().contains(search)||book.getPress().contains(search))
{
System.out.println(book+" 现有数量:"+ALL_BOOKS.get(book));
}
}
System.out.println("查询完毕");
System.out.println("请问是否继续?y/n");
String command = SYS_SC.nextLine();
switch (command)
{
case "y":
break;
default:
System.out.println("好的!");
return;
}
}
}
图书借阅信息查询:
遍历READERS_BOOKS集合:先遍历键值,在遍历每个键值对应的value值(即读者对应的借书信息)。这样既得到图书信息又得到借阅人信息。
public static void inquireLendInformation()
{
System.out.println("请输入书名:");
String bookName = SYS_SC.nextLine();
Set<Reader> howAreLending = READERS_BOOKS.keySet();
for (Reader reader : howAreLending)
{
for (Lend lend : READERS_BOOKS.get(reader))
{
if (Objects.equals(lend.getBook_in_lend().getName(),bookName))
{
System.out.println(lend);
}
}
}
System.out.println("查询完毕");
}
排序功能:
以读者排序为例,在读者类中定义类自带的排序功能;
先根据学院排序:
将所有学院放在ArrayList数组中,利用数组的索引进行排序;
再根据学号排序:
将学号转换成整数进行排序。
public class Reader extends User implements Comparable<Reader>, Serializable
{
private String academic;
private String subject;
private String GradeAndClass;
//省略set和get
@Override
public int compareTo(Reader o)
{
List<String> sizes = new ArrayList<>();
Collections.addAll(sizes,"信息学院","机械电子学院","经管学院","林学院","外国语学院","动科学院","资环学院");
if (Objects.equals(o.getAcademic(),this.getAcademic())==false)
{
return sizes.indexOf(o.getAcademic())-sizes.indexOf(this.getAcademic())>0?-1:1;
}
else if(Objects.equals(o.getNumber(),this.getNumber())==false)
{
return Integer.valueOf(o.getNumber())-Integer.valueOf(this.getNumber())>0?-1:1;
}
else
{
return 0;
}
}
}
删除功能,修改功能:
两者都需要找到要进行操作的对象,因此可以定义一个方法根据学号/书号找到对象,让删除和修改方法调用。
以图书信息删除为例:
public static Book getBookByInput(String InPut)//通过书名/书号获取图书对象
{
Set<Book> books = ALL_BOOKS.keySet();
for (Book book : books)
{
if (Objects.equals(book.getName(),InPut)||Objects.equals(book.getNumber(),InPut))
return book;
}
return null;
}
private static void deleteBook() throws IOException//下架图书
{
while (true)
{
System.out.println("===============下架图书================");
if (ALL_BOOKS.size() == 0)
{
System.out.println("当前无图书可下架");
}
System.out.println("请输入需要下架图书的名称/书号:");
String input = SYS_SC.nextLine();
Book x2 = getBookByInput(input);
if(x2 != null)
{
System.out.println(x2);
System.out.println("是否确认下架《"+x2.getName()+"》 y/n");
String choice = SYS_SC.nextLine();
if (Objects.equals(choice,"y"))
{
ALL_BOOKS.remove(x2);
oos = new ObjectOutputStream(new FileOutputStream("src/wryyyyy/ALL_BOOKS"));
oos.writeObject(ALL_BOOKS);
System.out.println("您已成功下架了" + x2.getName());
}
}
else
{
System.out.println("馆内没有该图书");
}
System.out.println("请问是否继续?y/n");
String command = SYS_SC.nextLine();
switch (command)
{
case "y":
break;
default:
System.out.println("好的!");
return;
}
}
}
添加功能:
添加时应根据学号/书号判断是否重复添加;
以读者信息添加为例:
private static void addReader() throws IOException//添加读者
{
while (true)
{
System.out.println("===============添加读者================");
System.out.println("请输入读者名:");
String name = SYS_SC.nextLine();
System.out.println("请输入读者学号(7位数字):");
String number = SYS_SC.nextLine();
System.out.println("请设置读者登录密码(6位数子):");
String password = SYS_SC.nextLine();
System.out.println("请输入学院(信息学院,机械电子学院,经管学院,林学院,外国语学院,动科学院,资环学院):");
String academic = SYS_SC.nextLine();
System.out.println("请输入专业:");
String subject = SYS_SC.nextLine();
System.out.println("请输入年级和班级(如21-10):");
String GradeAndClass = SYS_SC.nextLine();
Reader reader = new Reader(name,number,password,academic,subject,GradeAndClass);
if (findUserNumberByInput(number)==null)
{
Set<Lend> personal_lend = new HashSet<>();
ALL_USERS.add(reader);
READERS_BOOKS.put(reader,personal_lend);
oos = new ObjectOutputStream(new FileOutputStream("src/wryyyyy/USERS.txt"));
oos.writeObject(ALL_USERS);
oos = new ObjectOutputStream(new FileOutputStream("src/wryyyyy/READERS_BOOKS"));
oos.writeObject(READERS_BOOKS);
System.out.println("添加成功:"+reader.getName());
}
else
{
System.out.println("该用户以存在!");
}
System.out.println("请问是否继续?y/n");
String command = SYS_SC.nextLine();
switch (command)
{
case "y":
break;
default:
System.out.println("好的!");
return;
}
}
}
展示信息表功能:
对于既要展示键值又要展示value值的集合,应该先遍历提取出来的键值输出,在通过键值获取value值并输出。
以展示图书信息表为例:
private static void scanBook()//浏览全部图书
{
System.out.println("===================图书信息表===================");
//提取键值
Set<Book> books = ALL_BOOKS.keySet();
for (Book book : books)
{
System.out.println(book+" 现有数量:"+ALL_BOOKS.get(book));
}
}
图书借阅/归还功能:
图书借阅时,先判断现有数量是否大于0,大于0则可以借出;
图书借出后,获取当时时间并转化为字符串形式写入图书借阅信息,并添加到READERS_BOOKS集合(键值为读者信息,value值为读者的图书借阅信息)和ALL_IN_LEND集合中,图书现有数量-1;
图书归还同理;
private static void borrowBook() throws IOException//借出图书
{
//现存数量大于0可以借出(get value值)ok
//借出后修改图书信息表中现存数量(修改value值)ok
//名字添加到图书借阅表,个人信息表也写上->lend对象 ok
while (true)
{
System.out.println("==================图书借阅==================");
System.out.println("请输入书号/书名:");
String input = SYS_SC.nextLine();
Book book = getBookByInput(input);
System.out.println(book);
if(book!=null)
{
if(ALL_BOOKS.get(book)>0)
{
System.out.println("是否确认借出y/n");
String choice = SYS_SC.nextLine();
if (Objects.equals(choice,"y"))
{
ALL_BOOKS.put(book,ALL_BOOKS.get(book)-1);
Date d = new Date();
long time = d.getTime();
String TimeFrom = sdf.format(time);
Lend lend = new Lend(book,(Reader) loginUser,TimeFrom,null);
READERS_BOOKS.get((Reader)loginUser).add(lend);
READERS_BOOKS.put((Reader) loginUser,READERS_BOOKS.get((Reader)loginUser));
oos = new ObjectOutputStream(new FileOutputStream("src/wryyyyy/READERS_BOOKS"));
oos.writeObject(READERS_BOOKS);
ALL_IN_LEND.addAll(READERS_BOOKS.get((Reader)loginUser));
oos = new ObjectOutputStream(new FileOutputStream("src/wryyyyy/ALL_IN_LEND.txt"));
oos.writeObject(ALL_IN_LEND);
oos = new ObjectOutputStream(new FileOutputStream("src/wryyyyy/ALL_BOOKS"));
oos.writeObject(ALL_BOOKS);
System.out.println("借阅成功!");
}
}
else
{
System.out.println("该图书以被借空,请一段时间后再来。");
}
}
else
{
System.out.println("馆内没有该图书!");
}
System.out.println("请问是否继续?y/n");
String command = SYS_SC.nextLine();
switch (command)
{
case "y":
break;
default:
System.out.println("好的!");
return;
}
}
}
private static void returnBook() throws IOException//归还图书
{
while (true)
{
System.out.println("==================图书归还==================");
System.out.println("请输入书号/书名:");
String input = SYS_SC.nextLine();
Book book = getBookByInput(input);
System.out.println(book);
Lend lend = getLendInformationByBook(book);
if (lend!=null)
{
System.out.println("是否确认归还y/n");
String choice = SYS_SC.nextLine();
if (Objects.equals(choice,"y"))
{
Date d = new Date();
long time = d.getTime();
String TimeTo = sdf.format(time);
lend.setTime_to(TimeTo);
Lend lend1 = lend;
ALL_BOOKS.put(book,ALL_BOOKS.get(book)+1);
oos = new ObjectOutputStream(new FileOutputStream("src/wryyyyy/READERS_BOOKS"));
oos.writeObject(READERS_BOOKS);
READERS_BOOKS.get((Reader)loginUser).add(lend);
ALL_IN_LEND.add(lend1);
oos = new ObjectOutputStream(new FileOutputStream("src/wryyyyy/ALL_IN_LEND.txt"));
oos.writeObject(ALL_IN_LEND);
oos = new ObjectOutputStream(new FileOutputStream("src/wryyyyy/ALL_BOOKS"));
oos.writeObject(ALL_BOOKS);
}
}
else
{
System.out.println("您没有借阅该书!");
}
System.out.println("请问是否继续?y/n");
String command = SYS_SC.nextLine();
switch (command) {
case "y":
break;
default:
System.out.println("好的!");
return;
}
}
}
其他:
用于上述操作页面进入后不止一次执行此操作,所以应该把页面对应的操作放到循环中,执行一次这个操作之后,可以选择继续(执行下一次循环)或者退出当前页面(return结束方法)。
System.out.println("请问是否继续?y/n");
String command = SYS_SC.nextLine();
switch (command)
{
case "y":
break;
default:
System.out.println("好的!");
return;
}
IO流的使用:
定义输入流和输出流对象(必须各只定义一个,否则会出错),执行方法时,分别读取不同文件中的数据并写入集合。
当执行showMain()方法时,每当增加删除等操作对集合产生影响,集合都会重新写入文件。
退出系统后执行文件关闭操作(为了避免当没有写入文件操作时输出流出错的情况,在showMain()方法外面会事先写入一次文件)。
读取文件如下:
static
{
try
{
ois = new ObjectInputStream(new FileInputStream("src/wryyyyy/ALL_BOOKS"));
Object o1 = ois.readObject();
ALL_BOOKS = (TreeMap<Book, Integer>)o1;
ois = new ObjectInputStream(new FileInputStream("src/wryyyyy/USERS.txt"));
Object o2 = ois.readObject();
ALL_USERS = (Set<User>)o2;
ois = new ObjectInputStream(new FileInputStream("src/wryyyyy/ALL_IN_LEND.txt"));
Object o3 = ois.readObject();
ALL_IN_LEND = (Set<Lend>) o3;
ois = new ObjectInputStream(new FileInputStream("src/wryyyyy/READERS_BOOKS"));
Object o4 = ois.readObject();
READERS_BOOKS = (TreeMap<Reader, Set<Lend>>)o4;
}
catch (IOException e)
{
throw new RuntimeException(e);
}
catch (ClassNotFoundException e)
{
throw new RuntimeException(e);
}
}
main方法如下:
public static void main(String[] args) throws IOException, ClassNotFoundException
{
oos = new ObjectOutputStream(new FileOutputStream("src/wryyyyy/USERS.txt"));
oos.writeObject(ALL_USERS);
showMain();
System.out.println("-----------------------");
ois.close();
oos.close();
System.out.println("欢迎下次光临");
System.out.println("-----------------------");
}
输出操作如下:
oos = new ObjectOutputStream(new FileOutputStream("src/wryyyyy/USERS.txt"));
oos.writeObject(ALL_USERS);
oos = new ObjectOutputStream(new FileOutputStream("src/wryyyyy/READERS_BOOKS"));
oos.writeObject(READERS_BOOKS);