题面 json简介 首先我们先简单了解一下json,以便更好的理解这次作业。Json是基于 JavaScript的一个子集,是一种开放的、轻量级的数据交换格式,采用独立于编程语言的文本格式来存储和表示数据,易于程序员阅读与编写,同时也易于计算机解析和生成,通常用于在 Web 客户端(浏览器)与 Web 服务器端之间传递数据。
下面给出了一个json格式的数据例子。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 { "object_type" : "TweetRaw" , "download_datetime" : "2022-07-06T17:04:48.030971+08:00" , "raw_value" : { "created_at" : "Sat Dec 04 17:16:55 +0000 2021" , "id" : 1467181131464609792 , "id_str" : "1467181131464609792" , "full_text" : "there are some contents" , "display_text_range" : [ 0 , 183 ] , "entities" : { "urls" : [ { "url" : "https://t.co/AQNqsGsPsx" , "expanded_url" : "https://rpc.flashbots.net" , "display_url" : "rpc.flashbots.net" , "indices" : [ 106 , 129 ] } , { "url" : "https://t.co/uY0UwIC7lp" , "expanded_url" : "https://docs.flashbots.net/flashbots-protect/rpc/quick-start#how-to-use-flashbots-protect-rpc-in-metamask" , "display_url" : "docs.flashbots.net/flashbots-prot…" , "indices" : [ 160 , 183 ] } ] } , "user_id" : 1406813839627153408 , "user_id_str" : "1406813839627153408" , "retweet_count" : 1 , "favorite_count" : 2 , "reply_count" : 1 , "quote_count" : 0 , "favorited" : true , "possibly_sensitive_editable" : false , "lang" : "zh" , "supplemental_language" : null , "self_thread" : { "id" : 1467180910961643520 , "id_str" : "1467180910961643520" } } }
通过上面这个例子,我们可以更好的理解Json的数据格式,Json的格式约定比较简单,易于理解,包括以下几点。
对象:Json中用大括号 { } 保存对象,对象可以包含多个 key/value(键/值)对。 在上面的例子中,整个json用一对大括号 { }包裹,所以整个json其实是一个json对象。同时”raw_value”、 “entities”、”self_thread”这些键对应的值也都是对象。
对象包含的数据存储在键:值对中
值(value)可以是双引号括起来的字符串(string)、数值(number)、true、false、 null、对象(object)或者数组(array)。 键:一个字符串。 值和名称间用冒号:分割
Json采用名称:值,这种键值对的形式来存储数据,冒号右侧的值可以是多种数据类型,就比如上面给出的例子中的”object_type”、”id”、”favorited”、”supplemental_language”、”raw_value”、 “display_text_range”这些属性,他们所对应的值分别是字符串、数值、boolean(true、false)、 null、对象和数组(array)。
数据由逗号,分隔 Json中数据用逗号,分割,从上面的例子可以看出,对象中的键值对用逗号分隔,但对象中的最后一个键值对后面没有逗号。同时数组中的数据也用逗号分隔,这一点与我们学习的其他语言相同。
数组:中括号 [ ] 保存数组,数组可以包含多个对象,当然也可以包含我们常见的字符串、数值等数据类型。 JSON 中数组值必须是合法的 JSON 数据类型(字符串, 数字, 对象, 数组, 布尔值或 null)。比如在上面的例子中,”display_text_range”属性对应的值存储了数字,”urls”属性对应的值存储了2个对象。
了解了Json数据结构后,Jsonline格式的数据顾名思义,就是把Json数据放在一行,作为一行字符串,便于进行数据交换。
本题格式 本题中爬取到的Jsonline数据有固定的格式和固定的键值对,在这里将jsonline转换为json格式,向同学们介绍。一个爬取到的数据例子如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 { "object_type" : "TweetRaw" , "download_datetime" : "2022-07-06 08:00" , "raw_value" : { "created_at" : "Sat Dec 04 17:16:55 2021" , "id" : 1467181131464609792 , "full_text" : "this is a retweet_count content" , "user_id" : 1406813839627153408 , "retweet_count" : 1 , "favorite_count" : 2 , "reply_count" : 1 , "possibly_sensitive_editable" : true , "lang" : "zh" , "emojis" : [ { "name" : "Grinning Face" , "emoji_id" : 12 , "count" : 2 } , { "name" : "Face With Tears of Joy" , "emoji_id" : 22 , "count" : 1 } ] } }
属性介绍
属性
值
object_type
字符串,整个json的对象类型,该值固定为”TweetRaw”
download_datetime
字符串,爬取这条json数据的时间,时间格式固定“年-月-日 时:分”,年为4位,月、日、时、分补足2位,例如 2022-08-13 08:00
raw_value
对象,包含这条推特的所有信息
created_at
字符串,该条推特发布时间,时间格式固定星期 月份 日期 时:分:秒 年,月份格式约定为{12: “Dec”, 11: “Nov”, 10: “Oct”,9: “Sep”, 8: “Aug”, 7: “Jul”,6: “Jun”, 5: “May”, 4: “Apr”,3: “Mar”, 2: “Feb”, 1: “Jan”};星期英文简写为{1: “Mon”, 2: “Tue”, 3: “Wed”, 4: “Thu”, 5: “Fri”, 6: “Sat”, 7: “Sun”}
id
数值,推特id,该id唯一不重复
full_text
字符串,推特内容,如果不包含任何内容为null(即 “full_text”:null)
user_id
数值,发表用户的id,该id唯一不重复
retweet_count
数值,转发数
favorite_count
数值,点赞数
reply_count
数值,评论数
possibly_sensitive_editable
布尔值,表示是否为敏感信息,true为敏感信息,false则非敏感信息
lang
字符串,语言
emojis
数组,存储这条推特所包含的所有表情包,如果不包含任何表情包为空列表
name
字符串,表情包名字
emoji_id
数值,表情包id
count
数值,该条推特里使用了多少个该表情
查询指令介绍
指令序号
输入指令格式
输出格式
1
Qdate user_id start_date~end_date
N N1 N2 N3
2
Qemoji id
name1 name2 …
3
Qcount start_date~end_date
N
4
Qtext id
full_text
5
Qsensitive user_id
N
6
Qlang id
Language
指令序号
指令含义
说明
1
查询字段以空格隔开,查询id为user_id的用户在start_date~end_date时间段(包含开始和截止日期)内发布推特的条数N,总转发数N1,总点赞数N2,总评论数N3,以空格分隔。
日期格式为year-month-day,年为4位,月、日的数字要以0补全为2位。如2022-08-08,2022-11-10
2
查询字段以空格隔开,查询id的推特所包含的emoji名字,并以count数量降序排列,count数量相等则以name字典序升序排列,输出的name之间以空格分隔。
若此id推特无任何表情包,为空列表,输出None
3
查询字段以空格隔开,查询一段时间内(包含开始和截止日期),json数据爬取的个数N。
日期格式同指令1中格式
4
查询字段以空格隔开,查询某id推特的内容。
输出原内容时两侧不需要加引号。若此id推特无内容,输出None。(无内容指的是”full_text”:null。对于”full_text”:””的情况,处理时把内容看作空串,不输出字符)
5
查询字段以空格隔开,查询某user_id用户发布的敏感内容条数N。
无
6
查询字段以空格隔开,查询某id推特语言属性。
输出原内容时两侧不需要加引号
请编写程序读入多行jsonline数据,并根据输入的查询指令给出对应输出,输出需进行换行。
输入输出 输入格式 首先输入多若干行Jsonline数据,每一条Jsonline为一条推特的信息。最后以一行END_OF_MESSAGE结尾。 其后为多条查询语句,每行一条。 具体的指令请参见上文的查询指令介绍。
输出格式 输出格式详见上文的查询指令介绍。
样例 输入:
1 2 3 4 5 6 7 8 9 { "object_type" : "TweetRaw" , "download_datetime" : "2022-07-06 08:00" , "raw_value" : { "created_at" : "Sat Dec 04 17:16:55 2021" , "id" : 1467181131464609792 , "full_text" : "content1" , "user_id" : 1406813839627153408 , "retweet_count" : 1 , "favorite_count" : 2 , "reply_count" : 1 , "possibly_sensitive_editable" : true , "lang" : "zh" , "emojis" : [ { "name" : "Grinning Face" , "emoji_id" : 12 , "count" : 2 } , { "name" : "Face With Tears of Joy" , "emoji_id" : 22 , "count" : 1 } ] } } { "object_type" : "TweetRaw" , "download_datetime" : "2022-07-10 08:00" , "raw_value" : { "created_at" : "Sat Dec 09 17:16:55 2021" , "id" : 1467181131464609793 , "full_text" : "content2" , "user_id" : 1406813839627153408 , "retweet_count" : 1 , "favorite_count" : 0 , "reply_count" : 0 , "possibly_sensitive_editable" : false , "lang" : "zh" , "emojis" : [ ] } } END_OF_MESSAGE Qdate 1406813839627153408 2021 -12 -04 ~2021 -12 -05 Qemoji 1467181131464609792 Qcount 2022 -07 -04 ~2022 -07 -06 Qtext 1467181131464609793 Qsensitive 1406813839627153408 Qlang 1467181131464609792
Jsonline转化成的对应Json的结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 { "object_type" : "TweetRaw" , "download_datetime" : "2022-07-06 08:00" , "raw_value" : { "created_at" : "Sat Dec 04 17:16:55 2021" , "id" : 1467181131464609792 , "full_text" : "content1" , "user_id" : 1406813839627153408 , "retweet_count" : 1 , "favorite_count" : 2 , "reply_count" : 1 , "possibly_sensitive_editable" : true , "lang" : "zh" , "emojis" : [ { "name" : "Grinning Face" , "emoji_id" : 12 , "count" : 2 } , { "name" : "Face With Tears of Joy" , "emoji_id" : 22 , "count" : 1 } ] } } { "object_type" : "TweetRaw" , "download_datetime" : "2022-07-10 08:00" , "raw_value" : { "created_at" : "Sat Dec 09 17:16:55 2021" , "id" : 1467181131464609793 , "full_text" : "content2" , "user_id" : 1406813839627153408 , "retweet_count" : 1 , "favorite_count" : 0 , "reply_count" : 0 , "possibly_sensitive_editable" : false , "lang" : "zh" , "emojis" : [ ] } }
输出:
1 2 3 4 5 6 1 1 2 1 Grinning Face Face With Tears of Joy1 content2 1 zh
样例解释 Qdate 1406813839627153408 2021-12-04~2021-12-05: 用户对应日期时间段内只发布了一条tweet,即第一条tweet,对应输出1 1 2 1。
Qemoji 1467181131464609792: 查询了第一条tweet内部的表情,按照上文的排序规则排序后,输出Grinning Face Face With Tears of Joy。
Qcount 2022-07-04~2022-07-06: 查询对应时间段内爬取的数据条数,该时间段爬取了第一个tweet,输出1。
Qtext 1467181131464609793: 查询了第2个tweet的full_text内容,输出content2。
Qsensitive 1406813839627153408: 查询了该用户发布的敏感内容条数,2个tweet都为该用户发布,只有第1个为敏感内容,输出1。
Qlang 1467181131464609792: 查询第1个tweet的语言,输出zh。
数据限制
在所有键值对中,只有”full_text“的值可能为null,其他的所有值约定不为null。此外,只有full_text的值可以为””,除了full_text其他字符串的值保证不为””(即双引号内保证存在至少一个字符)。
指令及数据中的用户user_id,推特的id,emoji的id均存在,数据范围不作保证。emoji的名字唯一不重复。
在字符串内部,规定不包含双引号。
键值对冒号:两侧不包含空格,用于间隔数据的逗号,两侧均没有空格。一行jsonline数据中,只有字符串类型的值内部包含空格。
有关数字的查询指令,保证输出的数值类结果的大小不超过int。
id类的属性(id, user_id,emoji_id)的值,可以有前导零,但01和1是不同的id(即不通过数值相等判断id相同)。
解题思路 本题其实需要训练的是递归下降算法,但是本人由于又懒又不想动脑子,就直接利用了本题给的jsonline全部都是固定格式这一点,直接使用正则表达式把每个对应数据都抠出来进行操作。
我的数据结构大概是:首先利用Main函数对每一行字符串进行读取,然后送入一个叫做jsonline的类对这一行jsonline处理,抠出所有的数据,最后再建立一个memory类,创建一个jsonline容器,将所有处理好的Jsonline放入其中,使用的时候便可以在容器中查找(其实和四五六次作业的数据结构是非常类似的)
首先就是在main函数中创建好jsonline和memory的类,并且读入endmessage前将字符串输入jsonline类处理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 Scanner scanner = new Scanner (System.in);Memory memory = new Memory ();while (true ) { String jsonline = scanner.nextLine(); if (jsonline.equals("END_OF_MESSAGE" )) { break ; } else { Jsonline input = new Jsonline (jsonline); input.matchJson(); input.matchRaw(); input.matchEmoji(); memory.setJsonline(input); } }
由于每一行就是一个新的jsonline,所以需要进入一行就创建一个jsonline类,同时我在jsonline类中创建了三个match函数用来正则匹配,这个之后再说,总之,在else中就是把字符串放入新建的Jsonline类进行处理,处理完成后就放入memory中的jsonline容器。
然后让我们看看jsonline中的正则匹配处理。 如果观察我们的输入格式,我们可以发现它可以被很好的分成三段:{……raw value:{……emojis:[……]}}
,所以针对这种格式我也对其分段处理,首先提出第一个大括号内的信息,然后分割出第二个大括号,再提取第二个大括号中的信息,分割出第三个中括号,最后提取第三个中括号中的信息。这也分别对应了上面的三个match。
首先就是对第一个大括号的匹配:
1 2 3 4 5 6 7 8 9 10 11 12 13 public Jsonline (String string) { this .string = string; }private String json = "\\{\".*?\":\".*?\",\".*?\":\"(.*?)\",\".*?\":\\{(.*)}}" ; private Pattern pattern1 = Pattern.compile(json);public void matchJson () { Matcher matcher1 = pattern1.matcher(string); matcher1.find(); Date date = new Date (matcher1.group(1 ), 1 ); date.changeForm(); this .downloadDate = date; this .rawValue = matcher1.group(2 ); }
我们首先将新读入的字符串初始化放在jsonline.string中,然后利用pattern1对其进行匹配。 这个正则表达式中,第一个括号中的是该推特的下载时间,而第二个括号就是我们要进一步处理的raw value的全部信息。所以首先我们要对下载时间进行处理。我们可以发现首先下载时间处理其实还是比较繁复,而且我们能看到后面还需要对发送时间进行处理。所以我就专门新建了一个Date类,专门对时间进行处理,同时对其年月日信息进行保存。
首先来看Date类的初始化函数:
1 2 3 4 5 private String input; public Date (String input, int flag) { this .input = input; this .flag = flag; }
由于我们想要把下载时间和发送时间都在这里进行处理,但是两个时间的处理方式不同,因此我新建了一个flag类用来存储该时间类型,1为下载时间,2为发送时间。以下是下载时间的处理方式:
1 2 3 4 5 6 7 8 9 public void changeForm () { if (flag == 1 ) { String[] date = input.split(" " ); String[] accurateDate = date[0 ].split("-" ); this .year = Integer.parseInt(accurateDate[0 ]); this .month = Integer.parseInt(accurateDate[1 ]); this .day = Integer.parseInt(accurateDate[2 ]); }
利用空格可以分离出年月日的部分,同时利用“-”可以将年月日分离,然后分别存入year,month和day,便于后续提取本日期信息进行比较。
我们可以再看看之后发送时间的处理方法(后续不再提及):
1 2 3 4 5 6 7 if (flag == 2 ) { String[] date = input.split(" " ); this .year = Integer.parseInt(date[4 ]); this .month = selectMonth(date[1 ]); this .day = Integer.parseInt(date[2 ]); }
同理,也是利用空格进行分割,分割后可以发现年份和日期可以直接字符串转化为数字得到,而月份给的是英文缩写,所以我又写了个selectMonth函数进行对应(这个函数原理很简单,就是如果检测到”Jan”就输出1,以此类推,不再赘述)
之后就是对rawValue的处理,这些都封装在Jsonline类中的matchRaw()函数中。 首先我们需要写出匹配rawValue的正则表达式,字符串如下(为了防止字符串过长导致的代码风格差,将其分成了几个部分进行合成)
1 2 3 4 5 6 private String raw1 = "\".*?\":\"(.*?)\",\".*?\":(.*?)," ;private String raw2 = "\".*?\":(.*?),\"user_id\":(.*?),\".*?\":(.*?)," ;private String raw3 = "\".*?\":(.*?),\".*?\":(.*?),\".*?\":(.*?)," ;private String raw4 = "\".*?\":\"(.*?)\",\".*?\":\\[(.*)]" ;private String raw = raw1 + raw2 + raw3 + raw4;private Pattern pattern2 = Pattern.compile(raw);
之后在matchRaw函数中利用捕获组分别捕获括号中的不同类型信息进行处理,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public void matchRaw () { Matcher matcher2 = pattern2.matcher(rawValue); matcher2.find(); Date date = new Date (matcher2.group(1 ), 2 ); date.changeForm(); this .createDate = date; this .twitterId = matcher2.group(2 ); if (matcher2.group(3 ).equals("null" )) { this .fullText = null ; } else { String fullText = matcher2.group(3 ).replace("\"" , "" ); this .fullText = fullText; } this .userId = matcher2.group(4 ); this .retweetCount = Integer.parseInt(matcher2.group(5 )); this .favouriteCount = Integer.parseInt(matcher2.group(6 )); this .replyCount = Integer.parseInt(matcher2.group(7 )); if (matcher2.group(8 ).equals("true" )) { this .possiblySensitive = true ; } else if (matcher2.group(8 ).equals("false" )) { this .possiblySensitive = false ; } this .usedLanguage = matcher2.group(9 ); this .emoji = matcher2.group(10 ); }
在这里我对每个捕获组捕获的内容都做了注释,但是对照捕获内容我们需要注意之前正则表达式中的几点:
最基本的就是对所有内容的捕获都需要用非贪婪捕获(.*?),防止出现匹配混乱(因为很多命名都可能扰乱捕获)
就是捕获fullText的部分不能使用\"(.*?)\"
而应该使用单纯的(.*?)
,这是因为可能为空,这样会让两侧括号无法匹配。但是这时由于推特内容中可能含有逗号让非贪婪捕获提前结束导致错误,所以后面的正则要写上\"user_id\":
,这样保证了提取的逗号一定是后续立即接上”user_id”子串的逗号,就不会出现问题。
就是最后一个捕获组的颜文字提取不能用非贪婪捕获,而应该按照现在的写法\\[(.*)]";
,因为无法保证颜文字字符串中没有右中括号],所以要贪婪匹配,由于其在字符串结尾,所以没有问题。
接下来就是对颜文字的提取,我们首先也是先写好正则表达式的字符串:
1 2 private String emojis = "(\\{(.*)},)*?(\\{(.*)})*" ;private Pattern pattern3 = Pattern.compile(emojis);
这就是以一个大括号(即一个颜文字)为单位构成的正则表达式,要注意如果要分组的话,前面的颜文字大括号后会跟一个逗号,而最后一个不会,所以要专门把最后一个大括号分出,并且都是用星号*,也就是匹配零个或多个。
然后就是对不同颜文字的分割和储存,我把储存功能交给一个容器emojiMemory,而分割功能我将其封装在matchEmoji()函数中,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 private ArrayList<Emoji> emojiMemory = new ArrayList <>();public void matchEmoji () { if (!emoji.equals("" )) { String[] everyEmoji = emoji.split("},\\{" ); for (int i = 0 ; i < everyEmoji.length; i++) { if (!(everyEmoji[i].startsWith("{\"name" ) || everyEmoji[i].startsWith("\"name" ))) { everyEmoji[i - 1 ] = everyEmoji[i - 1 ].concat("},{" + everyEmoji[i]); everyEmoji[i] = "notvalid" ; } } for (int i = 0 ; i < everyEmoji.length; i++) { if (!everyEmoji[i].equals("notvalid" )) { if (!everyEmoji[i].startsWith("{" )) { everyEmoji[i] = "{" .concat(everyEmoji[i]); } if (!everyEmoji[i].endsWith("}" )) { everyEmoji[i] = everyEmoji[i].concat("}" ); } Emoji newEmoji = new Emoji (everyEmoji[i]); newEmoji.emojiOperation(); emojiMemory.add(newEmoji); } } Collections.sort(emojiMemory); } }
其实这里很多代码都是我对于某些特殊情况的补救。我的原始思路是利用“},{”进行分割,这样就可以分出只缺少大括号的颜文字单元。但是遇到了两个问题:
首先是小问题,就是分割后缺少大括号,同时由于不知道位置我们不知道到底缺少了左大括号(最后一个颜文字)还是右大括号(第一个颜文字)还是都缺少(其他),因此我的补救方法就是对头尾进行判断,如果没出现大括号就补上一个。
然后是测试的时候发现的问题:居然有表情包的名字中带有“},{”子串,这样就会导致一个子串被切开,后续无法匹配。我给出的解决办法是,在分割完成之后直接先检测一遍,由于如果正确切割,那子串就应该以{“name”或”name”开头,所以只要开头没有检测到证明这个字串应该是连在上一个字串后而被错误切割了,我就将这一子串再连回上个子串后,再在这一错误子串位置留一个“notvalid”标记,后续处理时跳过即可。
(我感觉这些问题都是前期正则表达式设计的问题,其实应该改变正则表达式)
然后就是对分割出来的颜文字进行处理,此时我就新建了一个Emoji类进行处理,这里也是先正则表达式匹配然后对捕获组数据进行记录即可。代码如下,不再赘述:
1 2 3 4 5 6 7 8 9 10 private String input;private String emojiForm = "\\{\".*\":\"(.*)\",\".*\":(.*),\".*\":(.*)}" ;private Pattern emojiPattern = Pattern.compile(emojiForm);public void emojiOperation () { Matcher emojiMatcher = emojiPattern.matcher(input); emojiMatcher.find(); this .emojiName = emojiMatcher.group(1 ); this .emojiId = emojiMatcher.group(2 ); this .emojiCount = Integer.parseInt(emojiMatcher.group(3 )); }
然后就是由于输出时要求对颜文字进行排序,要求是以count数量降序排列,count数量相等则以name字典序升序排列。则需要在Emoji类中写一个compareTo函数并且接上Comparable<Emoji>接口。compareTo函数写法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Override public int compareTo (Emoji other) { if (this .emojiCount < other.emojiCount) { return 1 ; } else if (this .emojiCount > other.emojiCount) { return -1 ; } if (this .emojiName.compareTo(other.emojiName) < 0 ) { return -1 ; } else if (this .emojiName.compareTo(other.emojiName) > 0 ) { return 1 ; } return 0 ; }
这样只需要在前文处理字符串的最后加上一个sort函数即可。
接下来就是考虑对不同输入指令的输出,由于2,4,5,6指令都是简单的遍历推特并寻找符合条件推特提取特定信息,和之前作业较为相似,不再赘述。 主要是注意1,3指令的操作,我以第一个指令为例。 第一个指令要求是输出某一用户某一时间段内发布推特的数量,点赞量等等信息,其关键在于判断某一条推特的发布时间是否在这一规定时间段内。其他的操作都很简单,不再赘述。 我开始的思路是对年月日分别比较,只要分别在范围内即可。但是后来发现这种方法是有明显的Bug的,例如无法判断2021-12-31在2021-1-1和2022-1-1内,因为月份并不在范围内。 所以需要有优先级的比较,即年份相等再比月份,月份相等再比日期。第三个指令与其操作相同。具体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 boolean flag = true ;boolean flag1 = true ;boolean flag2 = true ;if (memory.get(i).getCreateDate().getYear() < firstYear) { flag1 = false ; } else if (memory.get(i).getCreateDate().getYear() == firstYear) { if (memory.get(i).getCreateDate().getMonth() < firstMonth) { flag1 = false ; } else if (memory.get(i).getCreateDate().getMonth() == firstMonth) { if (memory.get(i).getCreateDate().getDay() < firstDay) { flag1 = false ; } } }if (memory.get(i).getCreateDate().getYear() > lastYear) { flag2 = false ; } else if (memory.get(i).getCreateDate().getYear() == lastYear) { if (memory.get(i).getCreateDate().getMonth() > lastMonth) { flag2 = false ; } else if (memory.get(i).getCreateDate().getMonth() == lastMonth) { if (memory.get(i).getCreateDate().getDay() > lastDay) { flag2 = false ; } } } flag = flag1 & flag2;
以上就是最后一次作业啦!oopre虽然时间不长,但还是蛮有收获,希望下学期正式的oo能撑得住,听说很恐怖QAQ