javase综合案例3 -- 通讯录

一,项目要求

通讯录项目要实现:菜单打印,添加联系人,查看全部联系人,根据分组查看联系人,根据姓名关键字
查看联系人,根据电话关键字查看联系人,修改联系人,删除联系人,退出等。

基础功能

(1) 通过Idea创建一个名为contact的包,在包里创建一个联系人类Contact,包含姓名name,手机号码
phone,分组groupName属性,包含一个构造方法public Contact(String name, String phone),在构
造方法里通过name计算groupName的值,name的setter方法中也要根据name重新给groupName赋
值。
通过汉字转拼音工具类计算分组名称。
(2) 在包里创建一个通讯录接口ContactDao。此接口中提供通讯录相关的各种核心功能抽象方法:
页面方法 public void ui();
添加联系人public void addContact();
查看全部联系人 public void showAllContacts();
根据分组查看联系人 public void showContactsByGroupName();
根据姓名关键字查看联系人 public void showContactsByName();
根据手机号关键字查看联系人 public void showContactsByPhone();
修改联系人public void modifyContact();
删除联系人 public void deleteContactByName();
(3) 在包里创建一个通讯录实现子类ContactDaoImpl,定义一个全局的Map存储所有联系人(TreeMap最
合适,key是分组名, value是List< Contact >)。实现通讯录相关的各种核心功能:
(4) 在包里创建一个ContactTest类,在类的main方法里调用测试

拓展

  1. 在项目已有功能的基础上,添加如下功能:
    (1) 通讯录初始化时就包含5个人(自己以及自己的前后左右)。
    有如下几种方式:
    (1) 在AddressBook的构造方法中往Map中添加联系人
    (2) 在初始化代码块里往Map中添加联系人。
    (3) 自己写一个初始化方法public void init(); 在init方法中往Map里添加联系人, 然后在构造方
    法里调用init方法。
    (2) 给通讯录AddressBook类增加一个根据关键字查询联系人的功能public void
    showContactsByKeyword(String keyword),关键字既可以是姓名关键字也可以是手机号关键字

二,导入jar包 pinyin4j.jar

在项目目录下建立一个lib包,再将已经下载好的pinyin4j.jar包导入其中
(该工具包用以获取联系人首字母)
在这里插入图片描述

三,程序报下建立Pinyin4j类

在这里插入图片描述

package synthesisHomework.contact;

import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;

/**
 * 汉字转换成拼音方法
 *
 * @author 蔡龙
 */

public class Pinyin4j {

    HanyuPinyinOutputFormat format = null;

    public static enum Type {
        UPPERCASE,              //全部大写
        LOWERCASE,              //全部小写
        FIRSTUPPER            //首字母大写
    }

    public Pinyin4j() {
        format = new HanyuPinyinOutputFormat();
        format.setCaseType(HanyuPinyinCaseType.UPPERCASE);
        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
    }

    /**
     * 转换全部大写
     *
     * @param str 字符串
     * @return str为颐和园 ,return获取到的是YHY
     * @throws BadHanyuPinyinOutputFormatCombination
     */
    public String toPinYinUppercase(String str) throws BadHanyuPinyinOutputFormatCombination {
        return toPinYin(str, "", Type.UPPERCASE);
    }

    /**
     * 转换全部大写
     *
     * @param str   字符串
     * @param spera 转换字母间隔加的字符串,如果不需要为""
     * @return str为颐和园 ,spera为** return获取到的是Y**H**Y
     * @throws BadHanyuPinyinOutputFormatCombination
     */
    public String toPinYinUppercase(String str, String spera) throws BadHanyuPinyinOutputFormatCombination {
        return toPinYin(str, spera, Type.UPPERCASE);
    }

    /**
     * 转换全部小写
     *
     * @param str 字符串
     * @throws BadHanyuPinyinOutputFormatCombination
     * @return str为颐和园 ,return获取到的是yhy
     */
    public String toPinYinLowercase(String str) throws BadHanyuPinyinOutputFormatCombination {
        return toPinYin(str, "", Type.LOWERCASE);
    }

    /**
     * 转换全部小写
     *
     * @param str   字符串
     * @param spera 转换字母间隔加的字符串,如果不需要为""
     * @throws BadHanyuPinyinOutputFormatCombination
     * @return str为颐和园 ,spera为** return获取到的是y**h**y
     */
    public String toPinYinLowercase(String str, String spera) throws BadHanyuPinyinOutputFormatCombination {
        return toPinYin(str, spera, Type.LOWERCASE);
    }

    /**
     * 获取拼音首字母(大写)
     *
     * @param str 字符串
     * @return str为颐和园 ,return获取到的是Y
     * @throws BadHanyuPinyinOutputFormatCombination 异常信息
     */
    public String toPinYinUppercaseInitials(String str) throws BadHanyuPinyinOutputFormatCombination {
        String initials = null;
        String py = toPinYinUppercase(str);
        if (py.length() > 1) {
            initials = py.substring(0, 1);
        }
        if (py.length() <= 1) {
            initials = py;
        }
        return initials.trim();
    }

    /**
     * 获取拼音首字母(小写)
     *
     * @param str 字符串
     * @return str为颐和园 ,return获取到的是y
     * @throws BadHanyuPinyinOutputFormatCombination 异常信息
     */
    public String toPinYinLowercaseInitials(String str) throws BadHanyuPinyinOutputFormatCombination {
        String initials = null;
        String py = toPinYinLowercase(str);
        if (py.length() > 1) {
            initials = py.substring(0, 1);
        }
        if (py.length() <= 1) {
            initials = py;
        }
        return initials.trim();
    }

    /**
     * 将str转换成拼音,如果不是汉字或者没有对应的拼音,则不作转换
     *
     * @param str   字符串
     * @param spera 默认,可为""
     * @param type  转换格式
     * @return 按照转换格式转换成字符串
     * @throws BadHanyuPinyinOutputFormatCombination 异常信息
     */
    public String toPinYin(String str, String spera, Type type) throws BadHanyuPinyinOutputFormatCombination {
        if (str == null || str.trim().length() == 0) {
            return "";
        }
        if (type == Type.UPPERCASE) {
            format.setCaseType(HanyuPinyinCaseType.UPPERCASE);
        } else {
            format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        }
        String py = "";
        String temp = "";
        String[] t;
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            if ((int) c <= 128) {
                py += c;
            } else {
                t = PinyinHelper.toHanyuPinyinStringArray(c, format);
                if (t == null) {
                    py += c;
                } else {
                    temp = t[0];
                    if (type == Type.FIRSTUPPER) {
                        temp = t[0].toUpperCase().charAt(0) + temp.substring(1);
                    }
                    if (temp.length() >= 1) {
                        temp = temp.substring(0, 1);
                    }
                    py += temp + (i == str.length() - 1 ? "" : spera);
                }
            }
        }
        return py.trim();
    }
}



四,创建实体类Contact

题目中有一项要求是在构造器时通过name的值获取groupName的值
在这里使用到了Pinyin4j类中的方法

import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;

public class Contact {
    private String name;
    private String phone;
    private String groupName;

    public Contact() {
    }

    @Override
    public String toString() {
        return name+"("+phone+")" ;
    }

    public Contact(String name, String phone) throws BadHanyuPinyinOutputFormatCombination {
        this.name = name;
        this.phone = phone;
        //  使用pinyin4j获取姓名首字母
        this.groupName = new Pinyin4j().toPinYinUppercaseInitials(this.name);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) throws BadHanyuPinyinOutputFormatCombination {
        this.name = name;
        this.groupName = new Pinyin4j().toPinYinLowercaseInitials(this.name);

    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getGroupName() {
        return groupName;
    }

}

五,创建通讯录接口ContactDao

创建通讯录接口以规范其中用到的方法名

package synthesisHomework.contact;

import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;

public interface ContactDao {
//    页面方法
    void ui() throws BadHanyuPinyinOutputFormatCombination;
//    添加联系人
    void addContact() throws BadHanyuPinyinOutputFormatCombination;
//    查看全部联系人
    void showAllContacts();
//    根据分组查看联系人
    void showContactsByGroupName();
//    根据姓名关键字查看联系人
    void showContactsByName();
//    根据手机号关键字查看联系人
    void showContactsByPhone();
//    修改联系人
    void modifyContact() throws BadHanyuPinyinOutputFormatCombination;
//    删除联系人
    void deleteContactByName();

}

六,创建ContactDao接口的视线子类ContactDaoImpl

创建ContactDaoImpl类实现接口中的抽象方法

6.1 创建全局的Map对象和Scanner对象

Map<String, List<Contact>> map = new TreeMap<String, List<Contact>>();
Scanner sc = new Scanner(System.in);

6.2 插入至map的add方法

public void add(String name,String phone) throws BadHanyuPinyinOutputFormatCombination {
        Contact contact = new Contact(name,phone);
        //  如果没有分组则创建一个分组,并为该分组new一个ArrayList
        if(!map.containsKey(contact.getGroupName()))
            map.put(contact.getGroupName(),new ArrayList<Contact>());
        //  根据对应的key值加入输入的信息
        map.get(contact.getGroupName()).add(contact);
    }

6.3 初始化方法init

调用add方法将初始化信息加入到map中

public void init() throws BadHanyuPinyinOutputFormatCombination {
        add("小孤鸡","15577776666");
        add("大孤鸡","17788889966");
        add("中孤鸡","14728742783");
        add("黑孤鸡","18222778866");
        add("白孤鸡","19233337777");
    }

6.4 实现方法 ui 菜单

1.在进入菜单时优先调用init方法对通讯录进行初始化
2.再使用while无限循环进行菜单的输出
3.从控制台输入值并通过switch语句进行判断并跳转至对应的操作

@Override
    public void ui() throws BadHanyuPinyinOutputFormatCombination {
        //  初始放置五个数据
        init();
        while(true){
            System.out.println("=======通讯录=======\n" +
                    "1.添加联系人\n" +
                    "2.查看全部联系人\n" +
                    "3.根据分组查看联系人\n" +
                    "4.根据姓名关键字查看联系人\n" +
                    "5.根据电话关键字查看联系人\n" +
                    "6.修改联系人\n" +
                    "7.删除联系人\n" +
                    "8.关键字查询(姓名或电话)\n" +
                    "9.退出\n" +
                    "请输入您的选择(1-8): ");
            String n = sc.next();
            switch(n){
                case "1":addContact();break;
                case "2":showAllContacts();break;
                case "3":showContactsByGroupName();break;
                case "4":showContactsByName();break;
                case "5":showContactsByPhone();break;
                case "6":modifyContact();break;
                case "7":deleteContactByName();break;
                case "8":showContactsByKeyword();break;
                case "9":System.out.println("退出系统!");return;
                default:
                    System.out.println("输入错误,请重新输入");break;
            }
        }
    }

6.5 实现方法 addContact 添加联系人信息

1.使用while循环对姓名和电话进行录入
2.通过判断是否符合规定的正则表达式来跳出while循环(即判断姓名和电话是否合法)
3.将name和phone作为参数调用add方法,将信息插入到map中

@Override
    public void addContact() throws BadHanyuPinyinOutputFormatCombination {
        String name;
        String phone;
        //  判断联系人姓名是否符合规范
        while(true){
            System.out.println("请输入联系人姓名:");
            name = sc.next();
            if (!name.matches("^[\u4e00-\u9f5a]+$")) {
                System.out.println("姓名不合法,请重新输入");
                continue;
            }
            break;
        }
        //  判断联系人电话是否符合规范
        while(true){
            System.out.println("请输入联系人电话:");
            phone = sc.next();
            if (!phone.matches("^(13|14|15|17|18|19)\\d{9}$")) {
                System.out.println("电话号码不合法,请重新输入");
                continue;
            }
            break;
        }
        add(name,phone);
        //  添加成功
        System.out.println("添加成功!!!");
    }

6.6 实现方法 showAllContacts 查看所有联系人信息

1.判断是否为空
2.使用entrySet方法获取键值对并遍历输出所有信息

@Override
    public void showAllContacts() {
        //  entrySet方法获取键值对遍历输出
        if(map.isEmpty()) {
            System.out.println("还没有联系人哦!");
        }
        else {
            for (Map.Entry<String, List<Contact>> entry : map.entrySet()) {
                System.out.println(entry.getKey());
                for (Contact contact : entry.getValue()) {
                    System.out.println(contact);
                }
            }
        }
    }

6.7 实现方法 showContactsByGroupName 通过分组查询联系人

1.输入要查询的分组,并用正则表达式判断输入是否有误
2.将字符转为大写(在创建groupName时将首字母设为了大写)
3.通过map的get方法对比输入的分组信息
4.输出分组无联系人或者遍历输出所有该分组的联系人

@Override
    public void showContactsByGroupName() {
        System.out.println("请输入你要查询的分组:(a-z)");
        String c = "";
        while(true){
            c = sc.next();
            if(c.matches("^[A-Z|a-z]{1}$"))
                break;
            else System.out.println("只能输入一个字母哦!");
        }
        c=c.toUpperCase();
        //  通过map的get方法对比输入的分组信息
        Collection<Contact> contacts = map.get(c);
        //  如果不存在这个分组则直接return
        if(contacts == null) {
            System.out.println(c + "分组尚无联系人");
            return;
        }
        //  遍历输出分组对应的信息
        for(Contact contact : contacts){
            System.out.println(contact);
        }
    }

6.8 实现方法 showContactsByName 通过姓名关键字查询联系人

1.输入姓名关键字
2.用Collection 接收map中的values
3.设置计数器,因为找到的人可能不止一个
4.遍历values,通过contains方法比对关键字找出对应的信息并输出,计数器加一

@Override
    public void showContactsByName() {
        System.out.println("请输入姓名关键字:");
        String name = sc.next();
        //  用Collection 中的获取map中的值
        Collection<List<Contact>> values = map.values();
        //  计数,因为找到的人可能不止一个
        int count=0;
        //  遍历values,找到对应的信息
        for(List<Contact> list : values){
            for(Contact contact : list){
                if(contact.getName().contains(name)){
                    System.out.println(contact);count++;
                }
            }
        }
        //  如果一个也没有找到,输出提示信息
        if(count == 0){
            System.out.println("没有找到符合的联系人");
        }
    }

6.9 实现方法 showContactsByPhone 通过电话关键字查询联系人

类似于6.8

@Override
    public void showContactsByPhone() {
        System.out.println("输入电话关键字:");
        String phone = sc.next();
        //  用Collection 中的获取map中的值
        Collection<List<Contact>> values = map.values();
        //  计数,因为找到的人可能不止一个
        int count=0;
        //  遍历values,找到对应的信息
        for(List<Contact> list : values){
            for(Contact contact : list){
                if(contact.getPhone().contains(phone)){
                    System.out.println(contact);count++;
                }
            }
        }
        //  如果一个也没有找到,输出提示信息
        if(count == 0){
            System.out.println("没有找到符合的联系人");
        }
    }

6.10 实现方法 modifyContact 修改联系人信息

1.输入联系人全名
2.通过map中values方法遍历所有联系人信息
3.如果找到对应信息,预览并调用addContact方法进行新信息的插入
4.删除旧的信息,如果删除后,对应的组别内容为空,则将分组信息也删除

@Override
    public void modifyContact() throws BadHanyuPinyinOutputFormatCombination {
        System.out.println("请输入要修改的联系人的全名:");
        String name = sc.next();
        Collection<List<Contact>> values = map.values();
        for(List<Contact> list : values){
            for(Contact contact : list){
                if(contact.getName().equals(name)){
                    System.out.println("联系人信息:"+contact);
                    addContact();
                    //  先删除被修改过的信息
                    list.remove(contact);
                    //  再判断组别是否为空,为空的话删除组别信息
                    if(list.isEmpty())map.remove(contact.getGroupName());
                    System.out.println("修改成功");return;
                }
            }
        }
        System.out.println("要修改的联系人不存在");
    }

6.11 实现方法 delectContactByName 删除联系人信息

1.输入姓名全名
2.values遍历预览信息
3.判断是否确定删除
4.如果删除后组内为空,则删除分组

@Override
    public void deleteContactByName() {
        System.out.println("请输入要删除的联系人的姓名:");
        String name = sc.next();
        Collection<List<Contact>> values = map.values();
        for(List<Contact> list : values){
            for(Contact contact : list){
                if(contact.getName().equals(name)){
                    //  预览找到的联系人信息
                    System.out.println("联系人信息:"+contact);
                    //  是否删除
                    System.out.println("是否确定删除(Y/N)");
                    if(sc.next().equalsIgnoreCase("y")){
                        list.remove(contact);
                    }else return;
                    //  再判断组别信息是否为空,为空的话删除分组名
                    if(list.isEmpty())map.remove(contact.getGroupName());
                    System.out.println("删除成功");return;
                }
            }
        }
    }

6.12 实现方法 showContactsByKeyword 通过关键字(姓名或电话)查询联系人

1.输入关键字,定义计数器
2.遍历并比对关键字(姓名或电话),找到了则count++
3.判断计数器是否为0

public void showContactsByKeyword(){
        System.out.println("请输入关键字:");
        String keyword = sc.next();
        int count=0;
        Set<Map.Entry<String, List<Contact>>> entrys = map.entrySet();
        for(Map.Entry<String, List<Contact>> entry : entrys){
            for(Contact contact : entry.getValue()){
                if(contact.getName().contains(keyword)||contact.getPhone().contains(keyword)){
                    System.out.println(contact);
                    count++;
                }
            }
        }
        if(count == 0)
        System.out.println("没找到该联系人");
    }

七,测试

7.1 初始化通讯录

在这里插入图片描述

7.2 添加联系人

在这里插入图片描述

7.3 根据分组查询联系人

在这里插入图片描述

7.4 根据姓名关键字查询联系人

在这里插入图片描述

7.5 根据电话关键字查询联系人

在这里插入图片描述

7.6 修改联系人

在这里插入图片描述
在这里插入图片描述

7.7 删除联系人

在这里插入图片描述
在这里插入图片描述

7.8 关键字查询 (姓名或电话)

在这里插入图片描述
在这里插入图片描述

7.9 退出系统

在这里插入图片描述

  • 21
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小孤鸡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值