作業09-集合與泛型
1.本周學習總結
1.1 以你喜歡的方式(思維導圖或其他)歸納總結集合與泛型相關内容。
- 一、泛型的基本概念
泛型是JDK 1.5的一項新特性,它的本質是參數化類型(Parameterized Type)的應用,也就是說所操作的資料類型被指定為一個參數,在用到的時候在指定具體的類型。這種參數類型可以用在類、接口和方法的建立中,分别稱為泛型類、泛型接口和泛型方法。
-
二、關于向上轉型和向下轉型
為什麼會提到這個呢,主要是因為在沒有出現泛型之前,程式員是對Object引用進行“向下轉型”和“向上轉型”操作來實作某些類型的轉換。“向上轉型”是安全的,但是在“向下轉型中”若是用錯了類型就會出現異常。如:
package other;
public class Test {
private Object a; // 定義Object類型成員變量
public Object getA() { // 設定get方法
return a;
}
public void setA(Object a) { // 設定set方法
this.a = a;
}
public static void main(String[] args) {
Test t = new Test();
t.setA(new Float(12.3));
Integer f = (Integer)(t.getA());
System.out.println(f);
}
}
因為不存在文法錯誤,是以編譯器不會報錯,但是在運作的時候會出現ClassCastException的異常。由此看來,“向下轉型”操作通常會出現問題,而泛型機制可以很好的解決這個問題。
-
三、泛型的正常用法
1.泛型類的定義
泛型類是具有一個或多個類型變量的類,文法如下:
MutiOverClass<T1,T2> //MutiOverClass為泛型類名稱
2.泛型接口的定義
泛型接口和泛型類的定義方法類似,文法如下:
interface MutiOverInte<T1,T2>
3.泛型方法的定義
泛型方法的定義就比較複雜,其文法如下:
圖檔引用自這
- 四、類型通配符
在泛型機制中,提供了類型通配符,其主要作用是在建立一個泛型類對象時限制這個泛型類的類型實作或繼承某個接口或類的子類。要聲明這樣一個對象可以使用“?”通配符來表示,同時使用extends關鍵字來對泛型加以限制。
其文法如下:
泛型類名稱<? extends List> a = null
//<? extends List>表示類型未知,當需要使用該泛型對象時,可以單獨執行個體化
另外,泛型類不止可以向下限制,還可以進行向上限制,這就要用到
super
關鍵字即可,如
泛型類名稱<? super List> a = null
1.2 選做:收集你認為有用的代碼片段
//菱形文法
List<String> strList = new ArrayList<String>(); //java7以前
List<String> strList = new ArrayList<>(); //java7時
//java的foreach語句
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
numbers.stream().filter(i -> i % 2 == 0)..forEach(System.out::println);
//使用Map.Entry對元素進行周遊,并使用匿名内部類實作對map中元素的排序
List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(map.entrySet());
Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
@Override
public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) {
if (o1.getValue() == o2.getValue()) {
return o1.getKey().compareTo(o2.getKey());
}
return o2.getValue() - o1.getValue();
}
});
- 書面作業
本次作業題集
集合
1. List中指定元素的删除(題集題目)
1.1 實驗總結。并回答:列舉至少2種在List中删除元素的方法。
答:這題比較容易,就是一開始周遊List的時候,沒有考慮到從0開始周遊删除元素時後面元素下标的變化,導緻有些本該删除的元素沒有被删除。
在List中删除元素的方法:
//删除list中的偶數元素
List<Integer> list = new ArrayList<Integer>();
for(int i=0;i<10;i++){ //往list中添加元素
list.add(i);
}
//方法一:從前往後周遊删除元素
for(int i=0;i<list.size();i++){
if(list.get(i)%2==0){
list.remove(i);
i--;
}
}
//方法二:反向周遊删除元素
for(int i=list.size()-1;i>=0;i--){
if(list.get(i)%2==0)
list.remove(i);
}
//方法三:利用Iterator删除元素
for(Iterator<Integer> iterator = list.iterator();iterator.hasNext(); ){
int e = iterator.next();
if(e%2==0)
iterator.remove();
}
//方法四:建立一個新集合來删除元素
List<Integer> newList = new ArrayList<Integer>();
for(Integer e:list){
if(e%2==0)
newList.add(e);
}
list.removeAll(newList);
//方法五:利用removeIf删除某一個元素
list.removeIf(e -> e%2==0);
//輸出删除完成後清單(以上五個運作結果都一樣,就貼一張圖了)
System.out.println(list);
運作結果:
//方法六:利用forEach()過濾元素
list.stream().filter(e ->e%2==1).forEach(System.out::println);
2. 統計文字中的單詞數量并按出現次數排序(題集題目)
诶,上次的作業中似乎寫過了,那就照搬過來吧
2.1 僞代碼(不得複制代碼,否則扣分)
建立HashMap對象map
循環讀入文章中的單詞
IF 讀入單詞為”!!!!!”
退出循環
ELSE
IF map中沒有相應的key
添加單詞到map中并設定value為1
ELSE
将key對應的value值加1
建立ArrayList對象list
實作Collections接口對map對象進行排序
輸出map的長度
輸出排序後list中前十個資料
2.2 實驗總結
答:這題中用到了HashMap,key值為單詞,value值為單詞出現的次數,這題比較複雜的地方就是要使用一個能夠存放Map資料ArrayList來實作Collections接口來實作相應的排序。
關鍵代碼如下:
List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(map.entrySet());
Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
@Override
public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) {
if (o1.getValue() == o2.getValue()) {
return o1.getKey().compareTo(o2.getKey());
}
return o2.getValue() - o1.getValue();
}
});
其中Map.Entry為Map的一個内部接口,它表示Map中的一個實體(一個key-value對)。接口中有getKey(),getValue方法。使用它可以更友善我們去通路Map中的元素。
3. 反向索引(題集題目)
本題較難,做不出來不要緊。但一定要有自己的思考過程,要有送出結果。
3.1 截圖你的代碼運作結果
3.2 僞代碼(不得複制代碼,否則扣分)
建立Map對象map,其中key類型為String,value類型為ArrayList
建立ArrayList對象line
循環讀入文章中的單詞
IF 讀入單詞為"!!!!!"
退出循環
ELSE
IF map中沒有相應的key
添加單詞到map中并将目前行數的值添加到value中
ELSE
判斷目前行數是否已經存在于value中,若沒有,則添加目前行數到value中
建立疊代器Iterator
周遊輸出map中的内容
輸入一行字元串以空格分開
IF map中不同時存在指定單詞
輸出found 0 results
ELSE
求指定單詞的value值的交集
IF 交集為0
輸出found 0 results
ELSE
輸出交集以及交集中數字對應的行數
3.3 實驗總結
答:這題比較好玩的地方就是要在要将Map的value的類型設定為ArrayList的,以友善存儲單詞出現行數,然後要注意的點就是将某一單詞的目前行數加入ArrayList中時要判斷清單中是否已經存在該行的行數,即這個單詞是否在這行中出現多次,之前一直錯誤就是因為沒有考慮到一行可以存放多個相同單詞,然後使用Iterator疊代器進行Map的輸出。最後求單詞出現函數的實質其實就是求指定單詞的出現行數的交集,可以用retainAll方法來求。
4.Stream與Lambda
編寫一個Student類,屬性為:
private Long id;
private String name;
private int age;
private Gender gender;//枚舉類型
private boolean joinsACM; //是否參加過ACM比賽
建立一集合對象,如List,内有若幹Student對象用于後面的測試。
4.1 使用傳統方法編寫一個搜尋方法 List<Student> search(Long id, String name, int age, Gender gender, boolean joinsACM)
,然後調用該方法将id>某個值,name為某個值, age>某個值, gender為某個值,參加過ACM比賽的學生篩選出來,放入新的集合。在main中調用,然後輸出結果。(截圖:出現學号、姓名)
List<Student> search(Long id, String name, int age, Gender gender, boolean joinsACM)
測試資料:
List<Student1> student = new ArrayList<Student1>();
student.add(new Student1(1L,"wang",15,Gender.man,false));
student.add( new Student1(8L,"zhao",16,Gender.woman,true));
student.add( new Student1(87L,"chen",17,Gender.man,false));
student.add ( new Student1(100L,"xu",18,Gender.woman,false));
student.add( new Student1(67L,"chen",19,Gender.man,true));
student.add( new Student1(90L,"chen",20,Gender.man,true));
student.add( new Student1(177L,"chen",21,Gender.man,true));
//搜尋方法
static List<Student1> search(Long id, String name, int age, Gender gender, boolean joinsACM,List<Student1> list){
List<Student1> student = new ArrayList<Student1>();
for(Student1 e:list){
if(e.getId()>id&&e.getName().equals(name)&&e.getGender()==gender&&e.isJoinsACM()==joinsACM){
student.add(e);
}
}
return student;
}
//main函數
List<Student1> newStudent = search(50L, "chen",18,Gender.man, true,student);
for(Student1 e:newStudent){
System.out.println(e.toString());
}
}
運作截圖:
4.2 使用java8中的stream(), filter(), collect()編寫功能同4.1的代碼,并測試(要出現測試資料)。建構測試集合的時候,除了正常的Student對象,再往集合中添加一些null,你編寫的方法應該能處理這些null而不是抛出異常。(截圖:出現學号)
List<Student1> newStudent = student.stream().filter(e -> e!=null&&e.getId()>50&&e.getName().equals("chen")&&e.getAge()>18&&e.getGender()==Gender.man&&e.isJoinsACM()==true).collect(Collectors.toList());
測試資料(隻是添加了兩個null進去):
student.add(new Student1(1L,"wang",15,Gender.man,false));
student.add( new Student1(8L,"zhao",16,Gender.woman,true));
student.add(null);
student.add( new Student1(87L,"chen",17,Gender.man,false));
student.add(null);
student.add ( new Student1(100L,"xu",18,Gender.woman,false));
student.add( new Student1(67L,"chen",19,Gender.man,true));
student.add( new Student1(90L,"chen",20,Gender.man,true));
student.add( new Student1(177L,"chen",21,Gender.man,true));
其實和上面的結果是一樣的……
5. 泛型類:GeneralStack
題集
jmu-Java-05-集合
之GeneralStack
5.1 GeneralStack接口的代碼
interface GeneralStack<T>{
T push(T item);
T pop();
T peek();
public boolean empty();
public int size();
}
5.2 結合本題與以前作業中的 ArrayListIntegerStack
相比,說明泛型有什麼好處
ArrayListIntegerStack
答:在
ArrayListIntegerStack中
,棧中的元素隻能是Integer類型的,内容比較有局限性,而使用了泛型,則可以根據自己的要求來規定入棧元素的類型,就像這題中,我們隻要定義一個接口就可以實作對
Integer
、
Double
和
Car
類型的棧操作,減少了代碼的備援,使用起來也很靈活。
6. 選做:泛型方法
基礎參考檔案GenericMain,在此檔案上進行修改。
6.1 編寫方法max,該方法可以傳回List中所有元素的最大值。List中的元素必須實作Comparable接口。編寫的max方法需使得 String max = max(strList)
可以運作成功,其中strList為 List<String>
類型。也能使得 Integer maxInt = max(intList);
運作成功,其中intList為 List<Integer>
類型。注意:不得直接調用Collections.max函數。
String max = max(strList)
List<String>
Integer maxInt = max(intList);
List<Integer>
//max方法
public static <T extends Comparable<T>> T max(List<T> list){
Collections.sort(list);
return list.get(list.size()-1);
}
List<String> listA = new ArrayList<String>();
listA.add("aaaaa");
listA.add("bbbbb");
listA.add("ddddd");
listA.add("ccccc");
System.out.println(max(listA));
List<Integer> listB = new ArrayList<Integer>();
listB.add(11111);
listB.add(22222);
listB.add(44444);
listB.add(33333);
System.out.println(max(listB));
6.2 選做:現有User類,其子類為StuUser,且均實作了Comparable接口。編寫方法max1,基本功能同6.1,使得User user = max1(stuList);可以運作成功,其中stuList為List類型。也可使得Object user = max(stuList)運作成功。
//max1方法
public static <T extends Comparable< ? super T>> T max1(List<T> list,Comparator< ? super T> comp) {
Collections.sort(list,comp);
return list.get(list.size()-1);
}
List<StuUser> listC = new ArrayList<StuUser>();
listC.add(new StuUser(11, "aaa"));
listC.add(new StuUser(22, "bbb"));
listC.add(new StuUser(44, "ccc"));
listC.add(new StuUser(33, "eee"));
listC.add(new StuUser(33, "ddd"));
User user1 = max1(listC,new StuUserComparator());
Object user2 = max1(listC,new StuUserComparator());
System.out.println(user1);
System.out.println(user2);
6.3 選做:編寫 int myCompare(T o1, T o2, Comparator c)
方法,該方法可以比較兩個User對象,也可以比較兩個StuUser對象,傳入的比較器 c
既可以是 Comparator<User>
,也可以是 Comparator<StuUser>
。注意:該方法聲明未寫全,請自行補全。
int myCompare(T o1, T o2, Comparator c)
c
Comparator<User>
Comparator<StuUser>
//myCompare方法
public static <T> int myCompare(T o1,T o2, Comparator<? super T> c){
return c.compare(o1, o2);
}
User user1 = new User(123);
User user2 = new User(321);
int a = myCompare(user1,user2,new UserReverseComparator());
if(a<0)
System.out.println(user1+" > "+user2);
else if(a==0)
System.out.println(user1+" = "+user2);
else
System.out.println(user1+" < "+user2);
StuUser stu1 = new StuUser(44, "ccc");
StuUser stu2 = new StuUser(55, "ddd");
int b = myCompare(stu1,stu2,new StuUserComparator());
if(a<0)
System.out.println(stu1+" > "+stu2);
else if(a==0)
System.out.println(stu1+" = "+stu2);
else
System.out.println(stu1+" < "+stu2);
7. 選做:逆向最大比對分詞算法
集合實驗檔案中的第07次實驗(集合).doc檔案,裡面的題目6.
7.1 寫出僞代碼(不得直接複制代碼)
建立HashSet對象dic
Add word to dic
設定最大截取長度maxLength
While has nextLine{
Creat list
While line 的長度不為0{
從後往前以最大截取長度截取句子e
If dic.continue(e){
Add e to list
line = 截取字元串(0,line.size-e.size)
從後往前以最大截取長度截取句子e
}
Else
去掉e的第一個字元繼續操作
}
倒序輸出list中的元素
}
7.2 截圖你的代碼運作結果。
3.碼雲及PTA
題目集:
jmu-Java-05-集合
3.1. 碼雲代碼送出記錄
- 在碼雲的項目中,依次選擇“統計-Commits曆史-設定時間段”, 然後搜尋并截圖
3.2 截圖PTA題集完成情況圖
需要有兩張圖(1. 排名圖。2.PTA送出清單圖)
3.3 統計本周完成的代碼量
需要将每周的代碼統計情況融合到一張表中。
自己的目标能實作嗎?
恩第一周定的目标是到期末能夠寫7000+行的代碼,看樣子應該可以完成??
周次 | 總代碼量 | 新增代碼量 | 總檔案數 | 新增檔案數 |
---|---|---|---|---|
2 | 607 | 15 | ||
3 | 1642 | 1035 | 33 | 18 |
5 | 2044 | 402 | 42 | 9 |
6 | 2874 | 830 | 57 | |
7 | 3161 | 287 | 63 | |
8 | 4299 | 1138 | 72 | |
4831 | 532 | 81 | ||
10 | 5475 | 644 | 93 | 12 |
- 評估自己對Java的了解程度
嘗試從以下幾個次元評估自己對Java的了解程度
次元 | 程度 |
---|---|
文法 | pta的題目基本上沒問題吧,一些比較偏的文法也可以通過百度解決 |
面向對象設計能力 | 這方面的能力還比較弱,在設計購物車系統的時候充分暴露了出來,正在努力改善中 |
應用能力 | 也許借助一些資料可以完成一些簡單的工具? |
至今為止代碼行數 |