文章目录
- 一,项目要求
- 基础功能
- 拓展
- 二,导入jar包 pinyin4j.jar
- 三,程序报下建立Pinyin4j类
- 四,创建实体类Contact
- 五,创建通讯录接口ContactDao
- 六,创建ContactDao接口的视线子类ContactDaoImpl
- 6.1 创建全局的Map对象和Scanner对象
- 6.2 插入至map的add方法
- 6.3 初始化方法init
- 6.4 实现方法 ui 菜单
- 6.5 实现方法 addContact 添加联系人信息
- 6.6 实现方法 showAllContacts 查看所有联系人信息
- 6.7 实现方法 showContactsByGroupName 通过分组查询联系人
- 6.8 实现方法 showContactsByName 通过姓名关键字查询联系人
- 6.9 实现方法 showContactsByPhone 通过电话关键字查询联系人
- 6.10 实现方法 modifyContact 修改联系人信息
- 6.11 实现方法 delectContactByName 删除联系人信息
- 6.12 实现方法 showContactsByKeyword 通过关键字(姓名或电话)查询联系人
- 七,测试
- 7.1 初始化通讯录
- 7.2 添加联系人
- 7.3 根据分组查询联系人![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/a3d5d1e4e0984e2086284f18f21d28b2.png)
- 7.4 根据姓名关键字查询联系人
- 7.5 根据电话关键字查询联系人
- 7.6 修改联系人
- 7.7 删除联系人
- 7.8 关键字查询 (姓名或电话)
- 7.9 退出系统
一,项目要求
通讯录项目要实现:菜单打印,添加联系人,查看全部联系人,根据分组查看联系人,根据姓名关键字
查看联系人,根据电话关键字查看联系人,修改联系人,删除联系人,退出等。
基础功能
(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) 通讯录初始化时就包含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() {}@Overridepublic 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一个ArrayListif(!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语句进行判断并跳转至对应的操作
@Overridepublic 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中
@Overridepublic 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方法获取键值对并遍历输出所有信息
@Overridepublic 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.输出分组无联系人或者遍历输出所有该分组的联系人
@Overridepublic 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);// 如果不存在这个分组则直接returnif(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方法比对关键字找出对应的信息并输出,计数器加一
@Overridepublic 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
@Overridepublic 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.删除旧的信息,如果删除后,对应的组别内容为空,则将分组信息也删除
@Overridepublic 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.如果删除后组内为空,则删除分组
@Overridepublic 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 关键字查询 (姓名或电话)