知识总结
Set子接口
- 特点:无序、无下标、元素不可重复(当插入新元素时,如果新元素与已有元素进行equals比较,结果为true时,则拒绝新元素的插入)
- 方法:全部继承自Collection中的方法
foreach循环:
for(数据类型 变量名 : 容器名称){
}
可遍历集合或数组,常用在无序无序集合上
Set接口实现类
- HashSet:
(1)HashSet的底层使用的HashMap类,即是将所有需要存入HashSet的值,直接保存在HashMap中
(2)先判断hashCode是否一致,==比较地址,equals比较内容
LinkedHashSet:
底层使用LinkHashMap(链表结构)存储,节点形式单独存储数据,并可以指向下一个节点,通过顺序访问节点,可保留元素插入顺序 - TreeSet:
(1)实现了SortedSet接口,需求必须可以对元素排序
(2)所有插入元素,必须实现Comparable接口,覆盖comparaTo方法
(3)根据comparaTo方法返回0作为去重依据
Map体系集合
- Map:地图、映射
概念:存储一对数据(key-value),无序、无下标、键不可重复、值可以重复 - HashMap算法:拿任何一个对象号,通过hash(key)做运算,key>>>16(除以16),只能通过得到0~15之间的一个数组,作为插入数组的下标
(1)Hashtable: HashMap的线程安全版本
(2)TreeMap:自动对key做排序,根据comparaTo的返回值去重
(3)Properties: Hashtable子类,主要用于存储key和value都是字符串的情况,常在读取配置文件之后,保存文件中的键值对。
今日练习
import java.util.*;
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");
Set<String>set = new HashSet<String>();
set.addAll(list);
System.out.println(set.size());
}
}
选择正确的答案
A.编译不通过
B.编译通过,运行时异常
C.编译运行都正常,输出3
D.编译运行都正常,输出4
答:C
- 在如下的Worker类中,添加完equals方法的基础上,添加一个hashCode方法。
import java.util.ArrayList;
import java.util.List;
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");
}
public int hashCode(){
//1
}
public boolean equals(Object obj) {
if(this == obj){
return true;
}
if(obj == null){
return false;
}
if(obj.getClass() != this.getClass()){
return false;
}
Worker w = (Worker)obj;
if(this.name.equals(w.name) && this.age == w.age && this.salary == w.salary){
return true;
}
return false;
}
}
public class TestWorker{
public static void main(String[] args){
Worker worker1 = new Worker("zhang3",18,3000.0);
Worker worker2 = new Worker("li4",25,3500.0);
Worker worker3 = new Worker("wang5",22,3200.0);
Worker worker4 = new Worker("zhao6",24,3300.0);
List worker = new ArrayList();
worker.add(worker1);
worker.add(worker2);
worker.add(worker3);
worker.add(1, worker4);
worker.remove(worker3);
for(int i = 0 ; i < worker.size() ; i++){
System.out.println(((Worker) worker.get(i)).getName() + "\t" + ((Worker) worker.get(i)).getAge() + "\t" + ((Worker) worker.get(i)).getSalary());
}
for(int i = 0 ; i < worker.size() ; i++){
((Worker) worker.get(i)).work();
}
System.out.println(worker1.equals(worker2));
}
}
在1处有几种写法:
a.
return 0;
b.
int result = 0 ;
if(name != null)
result = name.hashCode();
return result + age;
c.
```java
return super.hashCode();
现在要把Worker类放入HashSet中,并希望在HashSet中没有重复元素,则下面说法正确的是:
A.三种说法都正确
B.a,b写法正确,c的效率更高
C.b写法正确,a,b写法都不正确
答:B
- 代码改错
import java.util.*;
class Worker {
int age;
String name;
double salary;
public Worker(){}
public Worker(String name, int age, double salary) {
this.age = age;
this.name = name;
this.salary = salary;
}
int hashCode(){
return name.hashCode() + age + salary;
}
public boolean equals(Worker w) {
if(w.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(new Worker(0,"jerry",18,2000));
System.out.println(set.size());
}
}
答:修改为
public int hashCode(){
return name.hashCode() + age + (int)salary;
}
public boolean equals(Object obj) {
if(this == obj){
return true;
}
if(obj == null){
return false;
}
if(obj.getClass() != this.getClass()){
return false;
}
Worker w = (Worker)obj;
if(w.name.equals(name)&& w.salary == salary && w.age == age){
return true;
}else{
return false;
}
}
set.add(new Worker("jerry",18,2000));
- 在Worker类的基础上,为Worker类增加相应的方法,使得Worker放入HashSet中时,Set中没有重复元素。编写相应的测试代码。
答:
import java.util.*;
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 hashCode(){
return this.name.hashCode() + this.age + (int)this.salary;
}
public boolean equals(Object obj) {
if(this == obj){
return true;
}
if(obj == null){
return false;
}
if(obj.getClass() != this.getClass()){
return false;
}
Worker w = (Worker)obj;
if(w.name.equals(this.name)&& w.salary == this.salary && w.age == this.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(new Worker("jerry",18,2000));
System.out.println(set.size());
}
}
- 关于下列Map接口中常用的方法:
(1)put方法表示放入一个键值对,如果键值对已存在则_____,如果键不存在则_______。
(2)remove方法接受_______个参数,表示_______。
(3)get方法表示_______,get方法的参数表示_______,返回值表示________。
(4)要想获得Map中所有的键,应该使用方法_______,该方法返回值类型为_______。
(5)要想获得Map中所有的值,应该使用方法_______,该方法的返回值类型为_______。
答:
(1)覆盖、存入
(2)一、键值
(3)get(Object key)、键值、键映射的值
(4)keySet()、键值
(5)get()、键值映射的值 - 利用Map,完成下面的功能:
从命令行读取一个字符串,表示一个年份,输出该年的世界杯冠军是哪个球队。
如果该年没有举办世界杯,则输出:没有举办世界杯。
附录:截止2009年,历届世界杯冠军、世界杯冠军以及对应夺冠年份:
答:
import java.util.HashMap;
import java.util.Scanner;
public class TestFoodballCamption {
public static void main(String[] args) {
System.out.println("请输入一个年份:");
Scanner input = new Scanner(System.in);
int years = input.nextInt();
HashMap<Integer,String>map = new HashMap<Integer,String>();
map.put(2006, "意大利");
map.put(2002, "巴西");
map.put(1998, "法国");
map.put(1994, "巴西");
map.put(1990, "德国");
map.put(1986, "阿根廷");
map.put(1982, "意大利");
map.put(1978, "阿根廷");
map.put(1974, "德国");
map.put(1970, "巴西");
map.put(1966, "英格兰");
map.put(1962, "巴西");
map.put(1958, "巴西");
map.put(1954, "德国");
map.put(1950, "乌拉圭");
map.put(1938, "意大利");
map.put(1934, "意大利");
map.put(1930, "乌拉圭");
if(map.get(years) != null)
System.out.println(years+"获得世界杯冠军的是:"+map.get(years));
else
System.out.println(years + "未举办世界杯");
}
}
- 已知某学校的教学课程安排如下:
(1)使用Map,以老师的名字为键,教授的课程名作为值,表示上述课程安排。
(2)增加了一位新老师Allen教JDBC
(3)Lucy改为教CoreJava
(4)遍历Map,输出所有的老师及老师教授的课程
(5)利用Map,输出所有教JSP的老师
答:
import java.util.HashMap;
public class TestTeacher {
public static void main(String[] args) {
HashMap<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");
map.put("Allen","JDBC");
map.put("Lucy", "CoreJava");
for(Map.Entry entry : map.entrySet())
System.out.println( entry.getKey() +"\t"+ map.get(entry.getKey()));
for(Map.Entry entry : map.entrySet()){
if(map.get(entry.getKey()) == "JSP")
System.out.println(entry.getKey());
}
}
}
- 有下面代码
import java.util.*;
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
- 在下面代码的基础上
import java.util.HashMap;
import java.util.Scanner;
public class TestFoodballCamption {
public static void main(String[] args) {
System.out.println("请输入一个年份:");
Scanner input = new Scanner(System.in);
int years = input.nextInt();
HashMap<Integer,String>map = new HashMap<Integer,String>();
map.put(2006, "意大利");
map.put(2002, "巴西");
map.put(1998, "法国");
map.put(1994, "巴西");
map.put(1990, "德国");
map.put(1986, "阿根廷");
map.put(1982, "意大利");
map.put(1978, "阿根廷");
map.put(1974, "德国");
map.put(1970, "巴西");
map.put(1966, "英格兰");
map.put(1962, "巴西");
map.put(1958, "巴西");
map.put(1954, "德国");
map.put(1950, "乌拉圭");
map.put(1938, "意大利");
map.put(1934, "意大利");
map.put(1930, "乌拉圭");
if(map.get(years) != null)
System.out.println(years+"获得世界杯冠军的是:"+map.get(years));
else
System.out.println(years + "未举办世界杯");
}
}
增加如下功能:读读入一只球队的名字,输出该球队夺冠的年份列表
答:
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class TestFoodballCamption {
public static void main(String[] args) {
System.out.println("请输入一支球队的名字:");
Scanner input = new Scanner(System.in);
String fc = input.next();
HashMap<Integer,String>map = new HashMap<Integer,String>();
map.put(2006, "意大利");
map.put(2002, "巴西");
map.put(1998, "法国");
map.put(1994, "巴西");
map.put(1990, "德国");
map.put(1986, "阿根廷");
map.put(1982, "意大利");
map.put(1978, "阿根廷");
map.put(1974, "德国");
map.put(1970, "巴西");
map.put(1966, "英格兰");
map.put(1962, "巴西");
map.put(1958, "巴西");
map.put(1954, "德国");
map.put(1950, "乌拉圭");
map.put(1938, "意大利");
map.put(1934, "意大利");
map.put(1930, "乌拉圭");
int i = 0;
for(Map.Entry entry : map.entrySet()){
if(map.get(entry.getKey()).equals(fc)){
i++;
System.out.println(fc+"获得世界杯冠军的年份是:"+entry.getKey());
}
}
if(i == 0)
System.out.println(fc + "未获得世界杯");
}
}
- 给定一个字符串,请输入该字符串由哪些字符组成,每个字符出现几次?
答:
import java.util.*;
public class TestStringNumber {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String str = input.next();
Map<Character,Integer> map = new HashMap<Character,Integer>();
for (char chr : str.toCharArray()) {
if(map.get(chr) == null)
map.put(chr, 1);
else
map.put(chr, map.get(chr) + 1);
}
System.out.println(map.entrySet());
}
}