Key Point:
- Collection 接口、Set接口、List接口基本操作
- List接口及其實現類
- Set接口及其實現類
- 迭代遍歷
- Hash算法與hashCode方法
- Comparable接口
- Map接口及其實現類
- 遍歷Map
- 泛型
問題:
1.填空
- Collection接口的特點是元素是/對象/;
- List接口的特點是元素/有/順序,/可以/重複;
- Set接口的特點是元素/無/順序,/不可以/重複;
- Map接口的特點是元素是/無序、無下標/,其中/值/可以重複,/鍵/不可以重複。
2.(List)有如下代碼
import java.util.ArrayList;
import java.util.List;
public class TestList {
public static void main(String[] args) {
List<String>list = new ArrayList<String>();
list.add("Hello");
list.add("World");
list.add(1,"Learn");
list.add(1,"Java");
printList(list);
}
public static void printList(List list) {
//1
for(int i = 0 ;i<list.size();i++) {
System.out.println(list.get(i));
}
System.out.println(list.toString());
}
}
要求:
I.把//1處的代碼補充完整,要求輸出list中所有元素的內容
II.寫出程序執行的結果
III.如果要把實現類由ArrayList換爲LinkedList,應該改哪裏?ArrayList和LinkedList使用上有什麼區別?實現上有什麼區別?
IV。如果要把實現類由ArrayList換爲Vector,應該改哪裏?ArrayList和Vector使用上有什麼區別?實現上有什麼區別?
//II.[Hello, Java, Learn, World]
//III.List list = new LinkedList()
- ArrayList【重點】:
數組結構實現,查詢快、增刪慢;
JDK1.2版本,運行效率快、線程不安全。
JDK8的ArrayList,實際初始長度是0
首次添加元素時,需要實際分配數組空間,執行數組擴容操作
真正向數組中插入數據,用的時候再創建,或再加載,有效的減低無用內存的空間。
可用於展示時——查詢居多
- LinkedList:
鏈表結構實現,增刪快,查詢慢。空間存儲不連續,線程不安全。
常用於購物車——增刪頻繁
// IV.List list = new Vector()
- Vector:
數組結構實現,查詢快、增刪慢;內存空間連續,初始大小10,java的最早集合。
3.(List)寫出下面程序的運行結果
import java.util.ArrayList;
import java.util.List;
public class TestList {
public static void main(String[] args) {
List<String>list = new ArrayList<String>();
list.add("Hello");
list.add("World");
list.add("Hello");
list.add("Learn");
list.remove("Hello");
list.remove(0);
for(int i = 0 ;i <list.size();i++) {
System.out.println(list.get(i));
}
}
}
Hello
Learn
4.(Set,List)
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class TestListSet {
public static void main(String[] args) {
List<String>list = new ArrayList<String>();
list.add("Hello");
list.add("Learn");
list.add("Hello");
list.add("Welcome");
list.remove("Hello");
Set<String> set = new HashSet<String>();
set.addAll(list);
System.out.println(set.size());
}
}
//編譯運行正常,輸出3
5.(List)已知有一個Worker類如下:
public class Worker {
private int age;
private String name;
private double salary;
public Worker() {}
public Worker(int age, String name, double salary) {
this.age = age;
this.name = name;
this.salary = salary;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public void work() {
System.out.println(name + "work");
}
}
完成下面的要求
1) 創建一個 List,在 List 中增加三個工人,基本信息如下:
姓名 年齡 工資
zhang3 18 3000
li4 25 3500
wang5 22 3200
2) 在 li4 之前插入一個工人,信息爲:姓名:zhao6,年齡:24,工資 3300
3) 刪除 wang5 的信息
4) 利用 for 循環遍歷,打印 List 中所有工人的信息
5) 利用迭代遍歷,對 List 中所有的工人調用 work 方法。
6) 爲 Worker 類添加 equals 方法
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Worker {
private int age;
private String name;
private double salary;
public Worker() {}
public Worker( String name,int age, double salary) {
this.age = age;
this.name = name;
this.salary = salary;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public void work() {
System.out.println(name + "work");
}
@Override
public String toString() {
return "name:" + name + "\tage:" + age + "\tsalary:" + salary;
}
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj == null) {
return false;
}
if (obj.getClass() != this.getClass()) {
return false;
}
Worker obj_temp = (Worker) obj;
if ((this.name == obj_temp.name || obj_temp.name != null
&& this.name.equals(obj_temp.name))
&& (this.age == obj_temp.age)
&& (this.salary == obj_temp.salary)) {
return true;
} else {
return false;
}
}
public static void main(String[] args) {
// 1) 創建一個 List,在 List 中增加三個工人,基本信息如下:
// 姓名 年齡 工資
// zhang3 18 3000
// li4 25 3500
// wang5 22 3200
List<Worker> list = new ArrayList<Worker>();
list.add(new Worker("zhang3", 18, 3000));
list.add(new Worker("li4", 25, 3500));
list.add(new Worker("wang5", 22, 3200));
// 2) 在 li4 之前插入一個工人,信息爲:姓名:zhao6,年齡:24,工資 3300
list.add(2, new Worker("zhao6", 24, 3300));
// 3) 刪除 wang5 的信息
list.remove(3);
// 4) 利用 for 循環遍歷,打印 List 中所有工人的信息
for (int i = 0; i < list.size(); i++) {
}
// 5) 利用迭代遍歷,對 List 中所有的工人調用 work 方法。
Iterator<Worker> it = list.iterator();
while (it.hasNext()) {
System.out.println(it.next().toString());
}
// 6) 爲 Worker 類添加 equals 方法--見上equals方法
}
}
6.(Set,Hash算法)爲上一題的Worker類,在添加完equals方法的基礎上,添加一個hashCode方法。
public int hashCode(){
//1
}
有幾種寫法:
I.return 0 ;
II.int result = 0;
if(name != null)result = name.hashCode();
result result+age;
III.return super.hashCode();
現在要把Worker類放入HashSet中,並希望在HashSet中沒有重複元素,則下面說法正確的是:
A.三種寫法都正確
B.I、II寫法正確,II的效率更高
C.II法正確,I、II寫法都不正確
B
7.(Set,Hash算法,方法覆蓋)代碼改錯
import java.util.*;
class Worker{
String name;
int age;
double salary;
public Worker() {}
public Worker(String name,int age,double salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
/*public*/ int hashCode() {
return /*(int) (*/name.hashCode() + age + salary/*)*/;
}
public boolean equals(Worker w/*Object obj*/) {
if(w.name ==/*.equals(name)*/ name && w.salary == salary && w.age==age) {
return true;
}else {
return false;
}
}
}
public class TestWorker {
public static void main(String[] args) {
Set<Worker> set = new HashSet<Worker>();
set.add(new Worker("tom",18,2000));
set.add(new Worker("tom",18,2000));
set.add(/*0,*/new Worker("jerry",18,2000));
System.out.println(set.size());
}
}
重寫父類方法,訪問修飾符的權限需要大於或等於父類,default默認修飾符的權限到非同包子類就無效了,即改爲public或者protected合適
重寫的equals方法中,傳入參數應該爲Object類型
set.add()在HashSet是無序的集合,不能在指定位置添加指定對象
8.(Set,Hash算法)在前面的Worker類基礎上,爲Worker類增加相應的方法,使得Worker放入HashSet中時,Set中沒有重複元素。並編寫相應的測試代碼。
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class Worker {
private int age;
private String name;
private double salary;
public Worker() {}
public Worker( String name,int age, double salary) {
this.age = age;
this.name = name;
this.salary = salary;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public void work() {
System.out.println(name + "work");
}
@Override
public String toString() {
return "name:" + name + "\tage:" + age + "\tsalary:" + salary;
}
@Override
public int hashCode() {
return (int) (name.hashCode() + age + salary);
}
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj == null) {
return false;
}
if (obj.getClass() != this.getClass()) {
return false;
}
Worker obj_temp = (Worker) obj;
if ((this.name == obj_temp.name || obj_temp.name != null
&& this.name.equals(obj_temp.name))
&& (this.age == obj_temp.age)
&& (this.salary == obj_temp.salary)) {
return true;
} else {
return false;
}
}
public static void main(String[] args) {
// 1) 創建一個 workers,在 workers 中增加三個工人,基本信息如下:
// 姓名 年齡 工資
// zhang3 18 3000
// li4 25 3500
// wang5 22 3200
Set<Worker> workers = new HashSet<Worker>();
workers.add(new Worker("zhang3", 18, 3000));
workers.add(new Worker("li4", 25, 3500));
workers.add(new Worker("wang5", 22, 3200));
for(Worker ws:workers) {
System.out.println(ws.toString());
}
}
}
9.(Map)關於下列Map接口中常見的方法:
I.put方法表示放入一個鍵值對,如果鍵已存在則/替換舊的/,如果 鍵不存在則/增加一個鍵值對/。
II.remove方法接收/一個/個參數,表示/刪除一個鍵值對/。
III.get方法表示/通過鍵查找值/,get方法的參數表示/鍵名/,返回值表示/該鍵對應值/
IV.要想獲得Map中所有的鍵,應該使用方法/keySet/,該方法返回值類型爲/set/。
V.要想獲得Map中所有的值,應該使用方法/values/,該方法返回值類型爲/Collection/。
要想獲得Map中的所有鍵值對的集合,應該使用方法entrySet,該方法返回一個Map.EntrySet類型所組成的Set。
10.(Map)利用Map,完成下面的功能:
從命令行讀入一個字符串,表示一個年份,輸出該年的世界盃冠軍是哪支球隊。
如果該年沒有舉辦世界盃,則輸出:沒有舉辦世界盃。
附錄:截止2009年,歷屆世界盃冠軍、世界盃冠軍以及對應的奪冠年份:
import java.util.HashMap;
import java.util.Scanner;
public class Map {
public static void main(String[] args) {
HashMap<String,String> map = new HashMap<String,String>();
map.put("1930", "烏拉圭");
map.put("1934", "意大利");
map.put("1938", "意大利");
map.put("1950", "烏拉圭");
map.put("1954", "德國");
map.put("1958", "巴西");
map.put("1962", "巴西");
map.put("1966", "英格蘭");
map.put("1970", "巴西");
map.put("1974", "德國");
map.put("1978", "阿根廷");
map.put("1982", "意大利");
map.put("1986","阿根廷");
map.put("1990","德國");
map.put("1994","巴西");
map.put("1998","法國");
map.put("2002","巴西");
map.put("2006","意大利");
Scanner sc = new Scanner(System.in);
System.out.println("請輸入一個年份:");
String str = sc.nextLine();
if(map.containsKey(str)==false) {
System.out.println(str+"年沒有舉辦世界盃");
}else {
System.out.println(str+"年奪冠的球隊是:"+map.get(str));
}
}
}
11.(Map)已知某學校的教學課程內容安排如下:
老師 課程
Tom CoreJava
John Oracle
Susan Oracle
Jerry JDBC
Jim Unix
Kevin JSP
Lucy JSP
完成下列要求:
I.使用Map,以老師的名字作爲鍵,教授的課程名作爲值,表示上述課程安排。
II.增加了一位新老師Allen教JDBC
III.Lucy改爲教CoreJava
IV.遍歷Map,輸出所有的老師及老師教授的課程
V.利用Map,輸出所有教JSP的老師。
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class TestMap {
public static void main(String[] args) {
//I
Map<String,String> map = new HashMap<String,String>();
map.put("Tom", "CoreJava");
map.put("John","Oracle");
map.put("Susan","Oracle");
map.put("Jerry","JDBC");
map.put("Jim","Unix");
map.put("Kevin","JSP");
map.put("Lucy","JSP");
//II
map.put("Allen","JDBC");
//III
map.put("Lucy","CoreJava");
//IV
Set<String> set = map.keySet();
for(Object key:set) {
System.out.println(key+"\t"+map.get(key));
}
//V
if(map.containsValue("JSP")==true) {
for(String k:map.keySet()) {
if(map.get(k).equals("JSP")) {
System.out.print("\t"+k+"="+"JSP");
}
}
}
}
}
12.(Set,HashSet,空指針)有下面代碼
import java.util.HashSet;
import java.util.Set;
class Student{
int age;
String name;
public Student() {}
public Student(String name,int age) {
this.name = name;
this.age = age;
}
public int hashCode() {
return name.hashCode()+age;
}
public boolean equals(Object o) {
if(o==null) return false;
if(o==this)return true;
if(o.getClass()!=this.getClass()) return false;
Student stu = (Student)o;
if(stu.name.equals(name) && stu.age==age) return true;
else return false;
}
}
public class TestHashSet {
public static void main(String[] args) {
Set<Student> set = new HashSet<Student>();
Student stu1 = new Student();
Student stu2 = new Student("Tom",18);
Student stu3 = new Student("Tom",18);
set.add(stu1);
set.add(stu2);
set.add(stu3);
System.out.println(set.size());
}
}
下列說法正確的是:
A.編譯錯誤
B.編譯正確,運行時異常
C.編譯運行都正確,輸出結果爲3
D.編譯運行都正確,輸出結果爲2
B Exception in thread "main" java.lang.NullPointerException
13.(Map)在原有世界盃Map的基礎上,增加如下功能:
讀入一支球隊的名字,輸出該球隊的年份列表。
例如:I.讀入”巴西”,應當輸出1958、1962、1970、1994、2002
II.讀入“荷蘭”,應當輸出“沒有獲得過世界盃”。
import java.util.HashMap;
import java.util.Scanner;
public class Map {
public static void main(String[] args) {
HashMap<String,String> map = new HashMap<String,String>();
map.put("1930", "烏拉圭");
map.put("1934", "意大利");
map.put("1938", "意大利");
map.put("1950", "烏拉圭");
map.put("1954", "德國");
map.put("1958", "巴西");
map.put("1962", "巴西");
map.put("1966", "英格蘭");
map.put("1970", "巴西");
map.put("1974", "德國");
map.put("1978", "阿根廷");
map.put("1982", "意大利");
map.put("1986","阿根廷");
map.put("1990","德國");
map.put("1994","巴西");
map.put("1998","法國");
map.put("2002","巴西");
map.put("2006","意大利");
Scanner sc = new Scanner(System.in);
System.out.println("請輸入一個年份:");
String str = sc.nextLine();
if(map.containsKey(str)==false) {
System.out.println(str+"年沒有舉辦世界盃");
}else {
System.out.println(str+"年奪冠的球隊是:"+map.get(str));
}
System.out.println("請輸入奪冠球隊:");
String str1 = sc.nextLine();
if(map.containsValue(str1)==false) {
System.out.println(str1+"隊沒有獲得過冠軍");
}else {
System.out.println(str1+"隊的奪冠年份是:");
for(String k:map.keySet()) {
if(map.get(k).equals(str1)) {
System.out.print("\t"+k);
}
}
}
}
}
14.(Map)給定一個字符串,請輸出該字符串由哪些字符組成,每個字符出現幾次?
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class NumberCount {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("請輸入一個字符串:");
String str = sc.nextLine();
//字符串轉數字
char[] chars = str.toCharArray();
Map<Character,Integer>map = new HashMap<Character,Integer>();
//遍歷字符數組
for(char c:chars) {
if(!map.containsKey(c)) {//字母首次出現記錄1
map.put(c,1);
}else {
map.put(c,map.get(c)+1);//每出現一次字符就覆蓋其value值+1
}
}
//打印結果
for(Character key:map.keySet()) {
System.out.println(key+"字符在字符串中出現了"+map.get(key)+"次");
}
}
}