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)+"次");
}
}
}