题目要求
根据附件中的QQ群聊天文件,读取其中的聊天记录,实现如下的方法:1)List getMessagesById(String id, Date beginTime, Date endTime):根据参数的id返回id对应的qq号码或者邮箱地址标识的聊天者在指定时间段内(beginTime与Date endTime之间)的所有聊天记录;2)getChatter():打印除了教师外的话唠(发言最多的)同学的QQ号(或邮箱)、名字(QQ群中的名字)。
解题思路:
下载要读取的文档:(山东科技大学Java学习交流群.txt)
https://mooc1-1.chaoxing.com/ueditorupload/read?objectId=e5ab362c913b5a20a027f64022fa806d
以下是我的代码
Date类
这个类,成员有年月日时分秒,记录聊头信息发出的时间,具体实现如下
// An highlighted block
//自定义的日期类,有年月日,时分秒六个属性,两个方法,一个用来计算年月日,一个用来计算时分秒
//通过这两个方法可以实现日期前后的比较,另外重写toString方法
public class Date {
public int year;
public int month;
public int day;
public int hour;
public int minute;
public int second;
public Date(int year, int month, int day, int hour, int minute, int second) {
this.year = year;
this.month = month;
this.day = day;
this.hour = hour;
this.minute = minute;
this.second = second;
}
public int calculteday() {
return year*365+month*30+day;
}
public int calculatehour() {
return hour*3600+minute*60+second;
}
public String toString() {
return year+"年"+month+"月"+day+"日"+hour+"时"+minute+"分"+second+"秒";
}
}
Message类
Message类有两个属性,一个Date属性,一个String属性,互相对应,String属性是聊天消息的内容,而Date则是这个聊天消息发出的时间,Message可以排序,具体实现是按照Date的前后排序,具体实现如下
// An highlighted block
//Message类实现信息的存储,有两个属性,一个Date类型,记录信息发出的时间,String类型的message记录信息内容
//Message类实现的Comparable接口,可以排序,compareTo()方法通过Date(日期)排序
public class Message implements Comparable<Message>{
private Date time;
private String message;
public Message(Date time, String message) {
this.time = time;
this.message = message;
}
public Message(Date time) {
this.time = time;
}
public Date getTime() {
return time;
}
public void setTime(Date time) {
this.time = time;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public int compareTo(Message o) {
if(this.time.calculteday()<o.getTime().calculteday())
return -1;
else if(this.time.calculteday()>o.getTime().calculteday())
return 1;
else {
if(this.time.calculatehour()<o.getTime().calculatehour())
return -1;
else if(this.time.calculatehour()>o.getTime().calculatehour())
return 1;
else
return 0;
}
}
public String toString() {
return message;
}
}
People类
People类的每一个对象都对应一个群成员,记录该成员的ID(即QQ号或者QQ邮箱)、群昵称、以及这个群成员所有的聊天消息(Message链表),因为读取文件要每行每行的读取,所以每读取一行的聊天消息,那么就将消息插入到Message链表中,并实现一次排序,这样读取完成后,每个群成员的聊天记录就会按照时间的先后排好序,查找的时候直接比较每一个Message对象的Date属性即可,具体实现如下
// An highlighted block
//People类有三个成员,一个String表示id,一个String表示群内的名字,一个容器类则是这个人所有的聊头记录,
//get、set方法无需多说,addChat(Message message)方法是向记录聊天记录的容器内添加新读取的聊头记录
//而sortchat()方法则是将记录聊头记录的容器按照时间先后的顺序排好序
import java.util.Collections;
import java.util.LinkedList;
public class People {
public String id;
public String name;
public LinkedList<Message> chat;
public People(String id, String name) {
this.id = id;
this.name = name;
this.chat = new LinkedList<Message>();
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public LinkedList<Message> getChat() {
return chat;
}
public void setChat(LinkedList<Message> chat) {
this.chat = chat;
}
public void addChat(Message message) {
this.chat.add(message);
}
public void sortchat() {
Collections.sort(chat);
}
public String toString() {
return id+" "+name;
}
}
ReadChat类
这个类是这个程序的关键所在,它主要用来读取文件,把文件中的所有人以及这些人各自的聊天记录保存到哈希表中,哈希表的key值是每个人的ID,value值是People类的对象,这个对象中保存有每个人的ID,群昵称,和他所有的聊天信息。
具体的读取算法是:每行每行读取,如果读取的这一行信息是时间、群成员信息,那么就将时间、群成员信息(ID、群昵称)提取出来,创建一个Date对象保存时间,两个String对象保存群成员信息,如果不是,那么这行信息就是聊天内容,那么就将聊天内容保存到一个String对象中,接着读取下一行,再次判断新读取的这一行信息是聊天内容还是时间、群成员信息,如果是聊天内容,那么就调用String的concat方法将聊天内容添加到保存聊天内容的String对象中,如果不是聊天内容,那就是时间、群成员信息,那么就创建一个Message对象,将本次循环的Date对象和聊天内容String对象作为形参,判定本次循环的群成员是否在哈希表中,如果在,直接在哈希表在找出该群成员,调用该群成员的addchat方法,将Message对象插入到该群成员的聊天记录链表;如果哈希表中不存在该成员,那么创建一个新的People对象,将群成员信息作为形参,并在创建完成以后,将Message对象插入
如此往复循环,知道读取到的字符串信息为null。
具体实现如下:
// An highlighted block
//这个类中的readchat()用来读取文档中的信息,并将信息存储到一个哈希表(allchater)中,返回这个哈希表
import java.io.*;
import java.util.HashMap;
public class ReadChat {
public static HashMap<String,People> readchat(){
HashMap<String,People> allchater = new HashMap<String,People>();
BufferedReader br = null;
File f = new File("山科大Java学习交流群.txt");
InputStreamReader fr = null;
try {
fr = new InputStreamReader(new FileInputStream(f),"UTF-8");
br = new BufferedReader(fr);
String s = br.readLine();
//for(int o=0;o<1014;o++) {
while(true) {
while("".equals(s)) {
s=br.readLine();
}
if(s==null)
break;
//sapce1记录第一个空格出现的位置,以此读取年月日
int space1 = 0;
for(int i=0;i<s.length();i++) {
if(Character.isWhitespace(s.charAt(i))) {
space1 = i;
break;
}
}
//tmp0是记录年月日的字符串
String tmp0 = s.substring(0, space1);
//space2记录第二个空格出现的位置,以此读取时分秒
int space2 = 0;
for(int i=space1+1;i<s.length();i++) {
if(Character.isWhitespace(s.charAt(i))) {
space2 = i;
break;
}
}
//用String的substring()方法提取出年月日和时分秒的字符串,
//再用split()方法提取成int类型,创建日期对象
//tmp1是记录时分秒的字符串
String tmp1 = s.substring(space1+1, space2);
//tmp2是记录群昵称和QQ号的字符串
String tmp2 = s.substring(space2+1, s.length()-1);
//将年月日、时分秒提取出来
String[] tday = tmp0.split("-");
String[] thour = tmp1.split(":");
int year = Integer.parseInt(tday[0]);
int month = Integer.parseInt(tday[1]);
int day = Integer.parseInt(tday[2]);
int hour = Integer.parseInt(thour[0]);
int minute = Integer.parseInt(thour[1]);
int second = Integer.parseInt(thour[2]);
Date date = new Date(year,month,day,hour,minute,second);
//将QQ号和群昵称提取出来
int flag = 0;
for(int i = 0; i<tmp2.length();i++) {
if((tmp2.charAt(i)=='('||tmp2.charAt(i)=='<')&&flag == 0) {
flag=i;
break;
}
}
String name = tmp2.substring(0, flag);
String id = tmp2.substring(flag+1, tmp2.length());
//将消息提取出来
String message = br.readLine();
while(true) {
String newline = br.readLine();
if(newline == null)
{
s = null;
break;
}
if("".equals(newline))
{
message = message.concat(newline);
}
else {
if(Character.isDigit(newline.charAt(0))&&Character.isDigit(newline.charAt(1))&&Character.isDigit(newline.charAt(2))&&Character.isDigit(newline.charAt(3))&&newline.charAt(4)=='-'&&Character.isDigit(newline.charAt(5))&&Character.isDigit(newline.charAt(6))&&newline.charAt(7)=='-'&&Character.isDigit(newline.charAt(8))&&Character.isDigit(newline.charAt(9))) {
//判断是消息还是日期姓名id
s = newline;
break;
}
else
message = message.concat(newline);
}
}
Message m = new Message(date,message);
//如果发消息的人已经在哈希表中存在,那么直接将消息添加到这个人的记录消息的容
//器类中即可,如果发消息的人在哈希表中还不存在,那么创建一个新的People插入到哈希表
if(allchater.containsKey(id)) {
allchater.get(id).addChat(m);
if(!name.equals(""))
allchater.get(id).setName(name);
allchater.get(id).sortchat();
}
else {
People people = new People(id,name);
people.addChat(m);
allchater.put(id, people);
}
}
}catch(FileNotFoundException e) {
System.out.println("文件未找到");
}catch(IOException e) {
System.out.println("文件读取错误");
}
return allchater;
}
}
主函数Main类
main函数主要就是对读取文件返回的哈希表进行操作,根据ID找这个人在某一时间段的聊天记录,因为哈希表中ID是key值,所以可以直接根据ID找出这个人所对应的People对象,这个人所对应的对象中包含一个聊天记录链表(Message)链表,在Message链表中找Date大于开始时间,小于结束时间的所有聊天记录,并插入到一个新的Message链表中返回,这样就实现了List<> getMessagesById(String id, Date beginTime, Date endTime)方法;另外,想找出说话最多的同学也就比较简单了,首先我们遍历哈希表(遍历每个同学),哪个同学对应的People对象的聊天记录链表(Message)链表size()方法(即链表长度)最大,那么该同学就是说话最多的同学,这样我们就实现了getChatter()函数
具体实现如下
// An highlighted block
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
HashMap<String, People> allchater = ReadChat.readchat();
System.out.println("输入你要查的id");
String id = input.next();
System.out.println("输入你查找的聊头记录的开始时间“年 月 日 时 分 秒”");
int yearbegin = input.nextInt();
int monthbegin = input.nextInt();
int daybegin = input.nextInt();
int hourbegin = input.nextInt();
int minutebegin = input.nextInt();
int secondbegin = input.nextInt();
Date beginTime = new Date(yearbegin, monthbegin, daybegin, hourbegin, minutebegin, secondbegin);
System.out.println("输入你查找的聊头记录的结束时间“年 月 日 时 分 秒”");
int yearend = input.nextInt();
int monthend = input.nextInt();
int dayend = input.nextInt();
int hourend = input.nextInt();
int minutend = input.nextInt();
int secondend = input.nextInt();
Date endTime = new Date(yearend, monthend, dayend, hourend, minutend, secondend);
LinkedList<Message> lm = (LinkedList<Message>) Main.getMessagesById(id, beginTime, endTime);
if (lm == null)
System.out.println("该成员不存在");
else {
if (lm.size() == 0)
System.out.println("该成员在这段时间内没有说话");
else {
System.out.println(allchater.get(id) + "在" + beginTime + "到" + endTime + "时间内,说的话为:");
for (int i = 0; i < lm.size(); i++) {
System.out.println(lm.get(i));
}
}
}
System.out.println("----------------");
People maxofmessage = Main.getChatter();
System.out.println("话痨的个人信息是:" + maxofmessage);
}
// 根据参数的id返回id对应的qq号码或者邮箱地址标识的聊天者在指定
// 时间段内(beginTime与Date endTime之间)的所有聊天记录
public static List<Message> getMessagesById(String id, Date beginTime, Date endTime) {
LinkedList<Message> list = new LinkedList<Message>();
HashMap<String, People> allchat = ReadChat.readchat();
People people = allchat.get(id);
if (people == null)
return null;
Message beginsay = new Message(beginTime, "");
Message endsay = new Message(endTime, "");
for (int i = 0; i < people.getChat().size(); i++) {
if (people.getChat().get(i).compareTo(beginsay) > 0 && people.getChat().get(i).compareTo(endsay) < 0) {
list.add(people.getChat().get(i));
}
}
return list;
}
// 打印除了教师外的话唠(发言最多的)同学的QQ号(或邮箱)、名字(QQ群中的名字)
public static People getChatter() {
People maxofmessage = null;
HashMap<String, People> allchat = ReadChat.readchat();
int sumofmessage = 0;
Set<String> keyset = allchat.keySet();
Iterator it = keyset.iterator();
while (it.hasNext()) {
String id = (String) it.next();
if (allchat.get(id).getChat().size() > sumofmessage && !id.equals("43760439")) {
maxofmessage = allchat.get(id);
sumofmessage = maxofmessage.getChat().size();
}
}
return maxofmessage;
}
}