图书馆案例-Set篇

32 阅读2分钟

1. 建立一个名为service的软件包,其中去建立一个bookService的类,用它来实现与图书相关的业务逻辑

2. 建立一个名为models的软件包。其中去建立一个bookModel的样例类,用它来实现图书对象。

3. 建立一个名为dao的软件包。其中去建立一个bookDAO的类,用它来实现对图书的文件读写。

4. 修改ui层的代码:在用户输入1之后,去调用bookService的相关方法去读出所有图书,并显示出来。

Map篇

图书样例类,封装图书核心属性:

@param id 图书ID

@param name 图书名称

@param author 作者

@param price 价格

@param category 分类

package models
case class BookModel(
                      id: String,
                      name: String,
                      author: String,
                      price: Double,
                      category: String
                    )

dao 包 - BookDAO.scala(数据访问层:文件读写)

package dao

import models.BookModel
import scala.io.Source
import java.io.{File, PrintWriter}
import scala.util.Try

/**
 * 图书数据访问对象(基于Set存储,自动去重)
 */
class BookDAO {
  private val bookFile = new File("books.txt")

  /**
   * 从文件读取所有图书,返回Set(自动去重)
   * @return 图书Set集合(ID相同的图书会被合并)
   */
  def readAllBooks(): Set[BookModel] = {
    if (!bookFile.exists()) {
      bookFile.createNewFile()
      return Set.empty[BookModel]
    }

    // 读取文件 → 按行解析 → 转换为Set(自动去重)
    Source.fromFile(bookFile)
      .getLines()
      .filter(_.nonEmpty)
      .map { line =>
        val parts = line.split(",")
        BookModel(
          id = parts(0).trim,
          name = parts(1).trim,
          author = parts(2).trim,
          price = parts(3).trim.toDouble,
          category = parts(4).trim
        )
      }
      .toSet  // 关键:转换为Set,自动去重(基于BookModel的ID哈希)
  }

  /**
   * 写入图书(先读取现有数据→去重→覆盖写入,保证文件中无重复)
   * @param book 要写入的图书
   * @return 写入是否成功
   */
  def writeBook(book: BookModel): Boolean = {
    Try {
      // 1. 读取现有图书(Set形式,已去重)
      val existingBooks = readAllBooks()
      // 2. 添加新图书(Set自动去重,若ID已存在则覆盖)
      val updatedBooks = existingBooks + book  // Set的+操作:存在则替换,不存在则添加

      // 3. 覆盖写入文件(保证文件数据与Set一致)
      val writer = new PrintWriter(bookFile)
      try {
        updatedBooks.foreach { b =>
          writer.println(s"${b.id},${b.name},${b.author},${b.price},${b.category}")
        }
      } finally {
        writer.close()
      }
    }.isSuccess
  }
}

service 包 - BookService.scala(适配 Set 返回值)

package service

import models.BookModel
import dao.BookDAO

/**
 * 图书业务逻辑服务(基于Set处理,支持自动去重)
 */
class BookService {
  private val bookDAO = new BookDAO()

  /**
   * 获取所有图书(返回Set,无重复)
   * @return 图书Set集合
   */
  def getAllBooks(): Set[BookModel] = {
    // 业务逻辑扩展:例如过滤价格大于10元的图书(使用Setfilter操作)
    bookDAO.readAllBooks().filter(_.price > 10.0)
  }

  /**
   * 添加图书(Set自动去重,ID重复时会更新图书信息)
   * @param book 图书对象
   * @return 添加是否成功
   */
  def addBook(book: BookModel): Boolean = {
    if (book.id.isEmpty || book.price <= 0) {
      false
    } else {
      bookDAO.writeBook(book)
    }
  }
}

 UI 层 - UI.scala(适配 Set 遍历,保留 map 格式化)

import service.BookService
import models.BookModel

object UI extends App {
  private val bookService = new BookService()

  // 模拟用户交互菜单
  println("===== 图书管理系统(Set版本)=====")
  println("1. 查看所有图书(自动去重)")
  println("2. 退出系统")
  print("请输入操作编号:")

  val input = scala.io.StdIn.readLine().trim

  input match {
    case "1" =>
      println("\n===== 所有图书列表(无重复)=====")
      val books: Set[BookModel] = bookService.getAllBooks()

      if (books.isEmpty) {
        println("暂无图书数据!")
      } else {
        // Set仍支持map操作,格式化输出每本图书
        books.map { book =>
          s"ID:${book.id}\n" +
            s"书名:${book.name}\n" +
            s"作者:${book.author}\n" +
            s"价格:¥${book.price.formatted("%.2f")}\n" +
            s"分类:${book.category}\n" +
            "------------------------"
        }.foreach(println)  // 遍历Set输出(顺序不保证,Set是无序的)
      }

    case "2" =>
      println("\n感谢使用,再见!")

    case _ =>
      println("\n输入无效,请输入正确的操作编号!")
  }
}