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 退出系统

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小孤鸡

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

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

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

打赏作者

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

抵扣说明:

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

余额充值