java实现数据结构课设:通讯录管理系统

发布时间 2023-04-24 14:36:02作者: 一往而深,

以下的代码通过java代码实现了一个简单的通讯录管理系统
1.通过java模拟链表来实现
2.实现来简单的增删改查
3.实现了通过文件来保存通讯录的信息
4.实现自定义异常来提示错误(就是想用以下自定义异常)
5.可以通过姓名和电话号码的字串来查找
6.保证了电话号码的唯一性

**进行文件保存时删除或者修改通讯录信息文件实现同步的应对策略:

  • Node类
import java.io.Serializable;

//通讯人员类
class Reporter implements Serializable
{
    private static final long serialVersionUID = 2l;
    //属性
   private String name;//姓名
   private int age;//年龄
   private String number;//电话号码
    public Reporter(){};//空参构造
    public Reporter(String name,int age,String number){
        setAge(age);
        setName(name);
        setNumber(number);
    }

    //行为
    public void setName(String name){
        this.name = name;
    }
    public void setAge(int age){
        if(age>0&&age<=100){
            this.age = age;
        }else {
           throw new AgeOutOfBoundsException(age+"不在0-100之间");
        }

    }
    public void setNumber(String number ){
        this.number = number;
    }
    public String getName(){
        return this.name;
    }
    public int getAge(){
        return this.age;
    }
    public String getNumber(){
        return this.number;
    }

}
//结点类
public class Node implements Serializable {//该类可以实现序列化
    private static final long serialVersionUID = 1l;//设置序列号
    //属性
   private  Reporter reporter;//通讯人员
    private Node next;//下一个结点的地址
    public Node(){};//空参构造
    public Node(Reporter reporter,Node next){
        setNext(next);
        setReporter(reporter);
    }
    //行为
    public void setReporter(Reporter reporter) {//设置通讯人员
        this.reporter = reporter;
    }
    public void setNext(Node next){//设置下一个结点的地址
        this.next = next;
    }
    public Reporter getReporter(){
        return this.reporter;
    }
    public Node getNext(){
        return this.next;
    }

}

  • 自定义异常类
//自定义异常类,用于提示输入的年龄错误
public class AgeOutOfBoundsException extends RuntimeException {
    //空参构造
    public AgeOutOfBoundsException (){}
    //有参构造
    public AgeOutOfBoundsException(String message){//用户赋值错误信息
        super(message);
    }
}

  • 结点工具类
import java.io.*;
import java.util.ArrayList;
import java.util.Scanner;

//结点工具类
public class Nodeutil {
    //定义序列化流并实例化
   public static ArrayList<Node> list = new ArrayList<>();//定义一个集合临时存储结点

    public static  int count;//记录结点的数量

    //私有构造函数
    private Nodeutil() {
    }



    //1.初始化链表
    public static void initList(Node head, int n) throws IOException { //p为头节点的地址,n为需要创建的结点数
        Scanner sc = new Scanner(System.in);
        Node q = head;//用于后面的连接结点
        String name;
        int age;
        String number;
        for (int i = 0; i < n; i++) {

            System.out.printf("请输入第%d个节点的姓名:\n", i + 1);
            name = sc.nextLine();
            System.out.printf("请输入第%d个节点的年龄:\n", i + 1);
            age = sc.nextInt();
            sc.nextLine();//接收多余的回车

            String tempNumber;//临时接收电话号码
            while (true){
                System.out.printf("请输入第%d个节点的电话号码:\n", i + 1);
                tempNumber = sc.nextLine();
                if(isUniqueNumber(head,tempNumber)){//电话号码有重复
                    System.out.println("电话号码输入重复,请重新输入!");
                }else {
                    break;
                }
            }
            number = tempNumber;
            //创建新结点
            Reporter reporter = new Reporter(name, age, number);
            Node node = new Node(reporter, null);
            list.add(node);//将结点添加到集合中
            serializeNode(list);//将该集合写入文件中
            //连接结点
            Node p = node;
            q.setNext(p);//让第一个结点的引用指向第二个结点

            q = p;//q移动到下一个结点
            count++;//结点的数量+1

        }

    }
    //2.遍历链表
    public static void showList(Node head){

        System.out.println("          姓名          年龄          电话号码");
        for (Node p = head.getNext(); p != null; p = p.getNext()) {

            System.out.printf("%12s",p.getReporter().getName());

            System.out.printf("%12d",p.getReporter().getAge());
            System.out.printf("%12s",p.getReporter().getNumber());
            System.out.println("");
            System.out.println("-----------------------------------------------------------------------");
        }
    }
    //3.按照位置删除
    public static boolean removeList(Node head,int pos) throws IOException {//传入头节点地址和删除的位置
        //进行删除位置合理性的判断
        if(pos<=0 ||pos>count){

            return false;
        }
        //1.找到要删除位置结点的前一个结点的地址
      Node p = head;//p初始指向头节点
      int n =0;//记录已经遍历了的结点个数
      while (n<pos-1){
          p = p.getNext();//遍历节点
          n++;//更新遍历结点的个数
      }
      //2.进行结点删除
        p.setNext(p.getNext().getNext());

        list.remove(pos-1);//删除集合中对应的结点
        serializeNode(list);//重新将修改后的集合添加到文件中
        count--;//结点数量-1(位置不当,可能下标越界)
        return true;
    }
    //3.插入结点
    public static boolean insertList(Node head ,int pos) throws IOException {//参数同上
        if(pos<=0||pos>count+1){

            return false;
        }
        //1.先找到前一个结点的地址
        int n =0;
        Node p = head;
        while (n<pos-1){
            p = p.getNext();
            n++;
        }
        //2.进行结点插入
        String name;
        int age;
        String number;
        //2.1结点填充
        Scanner st = new Scanner(System.in);
        System.out.println("请输入插入的姓名:");
        name  = st.nextLine();
        System.out.println("请输入插入的年龄:");
        age = st.nextInt();
        st.nextLine();//接收多余的回车
        String tempNumber;
        while (true) {
            System.out.println("请输入插入的电话号码:");
            tempNumber = st.nextLine();
            if(isUniqueNumber(head,tempNumber)){//电话号码重复
                System.out.println("输入的电话号码重复,请重新输入!");
            }else {
                break;
            }
        }
      number = tempNumber;
        Reporter reporter = new Reporter(name,age,number);
        Node node = new Node(reporter,null);
        //2.2结点连接
        node.setNext(p.getNext());
        p.setNext(node);
        count++;//结点数量+1
        list.add(pos-1,node);//将结点添加到集合中
        serializeNode(list);//重新将集合写入到文件中
        return true;
    }
    //4.修改结点
    public static  boolean alterList(Node head,int pos){
        if(pos<=0||pos>count){
            return false;
        }
        //1.先找到被修改结点的地址
        int n =0;
        Node p = head;
        while (n<pos){
            p = p.getNext();
            n++;
        }
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入修改后的姓名:");
        p.getReporter().setName(sc.nextLine());
        System.out.println("请输入修改后的年龄:");
        p.getReporter().setAge(sc.nextInt());
        sc.nextLine();//接收多余的回车
        String tempNumber  ;//临时接收电话号码
        while (true) {
            System.out.println("请输入修改后的电话号码:");
            tempNumber = sc.nextLine();
            if (isUniqueNumber(head, tempNumber)){
                System.out.println("电话号码重复,请重新输入");
            }else {
                break;
            }
        }

        p.getReporter().setNumber(tempNumber);
       //修改集合中的元素策略:先删除然后添加
        list.remove(pos-1);//先将该位置的结点删除
        list.add(pos-1,p);//将集合添加大指定位置
        return true;
    }
    //5.查询结点信息
    public static void inqureList(Node head,String str){
        //1.对链表的信息进行遍历
        boolean flag = false;//标记是否查询成功
        System.out.println("-------------------------------------------------------------------------------------");
        System.out.println("          姓名          年龄          电话号码");
        for (Node p = head.getNext(); p!=null ; p = p.getNext()) {

            if(p.getReporter().getName().contains(str)
                    ||p.getReporter().getNumber().contains(str)){
                System.out.printf("%10s%10d%10s\n",p.getReporter().getName(),p.getReporter().getAge(),p.getReporter().getNumber());
                System.out.println("-------------------------------------------------------------------------------------");
            }
        }

    }
    //6.菜单函数
    public static void menuList(){
        System.out.println("--------------------------------欢迎使用通讯录管理系统------------------------------------------------");
        System.out.println("  1.创建通讯录");
        System.out.println("  2.修改人员信息");
        System.out.println("  3.删除人员信息");
        System.out.println("  4.查询人员信息");
        System.out.println("  5.显示通讯录");
        System.out.println("  6.插入人员信息");
        System.out.println("  0.退出程序");
    }
    //7.清屏函数
    public static void clean(){
        for(int i=0;i<100;i++)
            System.out.println(" ");
    }
    //8.判断电话号码是否唯一
private static boolean isUniqueNumber(Node head,String number){
        //遍历链表进行电话号码比对
    for(Node p = head.getNext();p != null ;p = p.getNext()){
        if(p.getReporter().getNumber().equals(number)){
            return true;
        }
    }
    return false;
    }
    //序列化,将Node对象信息写入到文件中
    private static void serializeNode(ArrayList<Node> list) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\project\\node.txt"));

        oos.writeObject(list);//将集合存储到文件中


    }
    //反序列化,将Node对象写出到程序中
    public static Node unSerializeNode() throws IOException, ClassNotFoundException {
        //定义反序列化流
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\project\\node.txt"));

        list = (ArrayList<Node>)ois.readObject();
        Node node;//创建一个空结点
        node = new Node();
        Node head = node;//头指针指向空结点

        Node q = head;//指向头节点
        Node p = null;
        for (Node o : list) {//遍历集合
           p = o;
           q.setNext(p);
            q=p;//指针后移
            count++;//结点的数量+1
        }
        return head;
    }
}
  • 测试类
import java.io.IOException;
import java.util.Scanner;

public class NodeTest {

    public static void main(String[] args) throws InterruptedException, IOException, ClassNotFoundException {
        Node node;//创建一个空结点
        node = new Node();
        Node head = node;//头指针指向空结点
        head = Nodeutil.unSerializeNode();//进行反序列化操作
        Scanner sc = new Scanner(System.in);
        while (true){
            Nodeutil.menuList();
            System.out.println("请输入你的选择:");
            int choose = sc.nextInt();
            switch (choose){
                case (1):
                    System.out.println("请输入你需要创建的通讯录中的人数:");
                    int  n = sc.nextInt();


                    Nodeutil.initList(head,n);
                    System.out.println("创建通讯录成功!");
                    System.out.println("");
                    System.out.println("");
                    System.out.println("通讯录信息如下:");
                    Nodeutil.showList(head);
                    Thread.sleep(5000);
                   Nodeutil.clean();//清屏
                    break;
                case (2):
                    System.out.println("请输入要修改人员的位置:");
                    int pos = sc.nextInt();
                    boolean flag = Nodeutil.alterList(head,pos);
                    if(flag){
                        System.out.println("修改成功!");
                        System.out.println("");
                        System.out.println("");
                        System.out.println("修改后的通讯录信息如下:");
                        Nodeutil.showList(head);
                        Thread.sleep(5000);//停滞5s
                        Nodeutil.clean();//清屏
                    }else {
                        System.out.println("删除位置输入有误,请重新输入!");
                        Thread.sleep(5000);//停滞5s
                        Nodeutil.clean();//清屏
                    }
                    break;
                case 3:
                    System.out.println("请输入需要删除人员的位置:");
                    int p = sc.nextInt();
                    final boolean flag1 = Nodeutil.removeList(head, p);
                    if(flag1){
                        System.out.println("删除成功!");
                        System.out.println("");
                        System.out.println("");
                        System.out.println("删除后的通讯录如下:");
                        Nodeutil.showList(head);
                        Thread.sleep(5000);
                        Nodeutil.clean();
                    }else {
                        System.out.println("你输入的需要删除人员的位置有误,请重新输入!");
                        Thread.sleep(5000);
                    }
                    break;
                case 4:
                    System.out.println("请输入需要查询的人员的姓名或者电话号码:");
                    String str = sc.next();
                    System.out.println("查询到的信息如下:");
                   Nodeutil.inqureList(head,str);
                   Thread.sleep(5000);
                   Nodeutil.clean();
                   break;
                case 5:
                    System.out.println("通讯录信息如下:");
                    Nodeutil.showList(head);
                    Thread.sleep(5000);
                    break;
                case 6:
                    System.out.println("请输入要插入的位置:");
                    int p1 = sc.nextInt();
                    final boolean flag2 = Nodeutil.insertList(head, p1);
                    if(flag2){
                        System.out.println("插入成功!");
                        System.out.println("");
                        System.out.println("");
                        System.out.println("通讯录信息如下:");
                        Nodeutil.showList(head);
                        Thread.sleep(5000);
                        Nodeutil.clean();
                    }else {
                        System.out.println("输入的插入的位置有误!");
                        Thread.sleep(5000);
                        Nodeutil.clean();
                    }
                    break;
                case 0:
                    System.exit(1);
            }
        }
    }
}