- 日考
已知有类 class Worker{ private String name; private Integer age; private Double salary; public Worker(){}; // 无参构造 public Worker(String name,Integer age, Double salary){ this.age = age; this.name = name; this.salary = salary; } // get/set略 } 创建三个Worker对象属性分别为 阿森 18 3500.0 啊云 28 5500.0 啊黄 3 -2000.0 创建一个泛型集合存储三个Worker对象 从集合中删除下标为1的Worker对象 遍历集合打印Worker的name属性
演示的代码如下:
package com.txw.test;
import java.util.ArrayList;
import java.util.List;
class Worker{
private String name;
private Integer age;
private Double salary;
// 无参构造
public Worker(){
}
public Worker(String name,Integer age, Double salary){
this.age = age;
this.name = name;
this.salary = salary;
}
// get/set
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
}
public class Test{
public static void main(String[] args) {
/**
创建三个Worker对象属性分别为
阿森 18 3500.0
啊云 28 5500.0
啊黄 3 -2000.0
创建一个泛型集合存储三个Worker对象
从集合中删除下标为1的Worker对象
遍历集合打印Worker的name属性
*/
Worker w1 = new Worker("阿森",18,3500.0);
Worker w2 = new Worker("啊云",28,5500.0);
Worker w3 = new Worker("啊黄",3,-2000.0);
List<Worker> list = new ArrayList<>();
list.add(w1);
list.add(w2);
list.add(w3);
list.remove(1);
// 普通遍历
for (int i = 0; i < list.size(); i++) {
Worker worker = list.get(i);
System.out.println(worker.getName());
}
// 增强for遍历
for (Worker worker : list) {
System.out.println(worker.getName());
}
}
}
1 Set接口
- 概念:Set接口是Collection的子接口。
- 特点:无序、无下标、不可重复的。
- 方法:均继承自Collection。
使用方式:
package com.txw.test;
import java.util.HashSet;
import java.util.Set;
public class TestSet {
public static void main(String[] args) {
// 创建一个Set集合
Set<String> set = new HashSet<>();
// 存放元素
set.add(new String("阿森"));
set.add(new String("阿云"));
set.add(new String("啊龙"));
set.add(new String("旺哥"));
set.add(new String("阿黄"));
// 重复的对象
set.add(new String("阿森"));
// 获取有效元素个数
System.out.println( set.size() ); // 3
// 获取元素由于没有下标只能使用forEach遍历
for(String str : set){
System.out.println( str );
}
}
}
1.1 实现类
1.1.1HashSet
- hash:散列表。
- ArrayList:数组实现,查询快,增删慢。
LinkedList:链表实现,查询慢,增删快。 - Set:数组+链表实现,hash表。
- hashCode:哈希码,Object中提供的方法,可以使用hashCode()方法获取一个对象的哈希码
Object中的hashCode是根据内存地址生成的一个int类型整数。 - hashCode生成原则:每个不同的对象尽量不一样,相同的对象一样。
hashCode不仅决定了对象的存储位置,HashSet还要通过hashCode验证对象是否为重复对象。 - HashSet验证重复的方式:
1. 获取对象的hashCode 如果hashCode不同HashSet认为不是重复的对象。 2. 如果hashCode相同,HashSet认为对象有可能重复,再次调用equals进行确认。
- 由于Object中的hashCode根据地址生成的HashCode,所以地址不同HashSet就认为这是不同的对象,在程序设计过程中地址不同而属性相同我们也认为对象是重复的。
覆盖Object中的HashCode,根据属性生成一个hashCode。
覆盖形式例:class Student{ String name; Integer age; Double score; @Override public int hashCode(){ // 将所有属性的hashCode合并为一个,返回 return name.hashCode()+age.hashCode()+score.hashCode(); } }
- HashSet存储元素时先调用hashCode如果hashCode一致会在调用equals,
使用HashSet时如果存储自定义类型,务必覆盖hashCode于equals两个方法。
程序设计过程中,hashCode与equals经常会一起(被)使用,所以有equals的地方也要添加hashCode。class Student{ String name; Integer age; Double score; @Override public int hashCode(){ // 将所有属性的hashCode合并为一个,返回 return name.hashCode()+age.hashCode()+score.hashCode(); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; return Objects.equals(name, student.name) && Objects.equals(age, student.age) && Objects.equals(score, student.score); } }
演示的代码如下:
package com.txw.test;
import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Set;
public class TestHashSet {
public static void main(String[] args) {
Student stu1 = new Student("阿森",18,90D);
System.out.println(stu1.hashCode()); // 356573597
Student stu2 = new Student("阿云",28,100D);
System.out.println(stu2.hashCode()); // 1735600054
Student stu3 = new Student("阿森",38,10D);
System.out.println(stu3.hashCode());` // 1077334155
Student stu4 = new Student("阿森",38,10D);
System.out.println(stu4.hashCode()); // 1077334155
Set<Student> set= new LinkedHashSet<>();
set.add( stu1 );
set.add( stu2 );
set.add( stu3 );
set.add( stu4 );
for (Student student : set) {
System.out.println( student );
}
}
}
class Worker{
String name;
Integer age;
Double salary;
// 属性私有提供get/set
// 有参、无参方法
//toString,equals,hashCode
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Worker worker = (Worker) o;
return Objects.equals(name, worker.name) && Objects.equals(age, worker.age) && Objects.equals(salary, worker.salary);
}
@Override
public int hashCode() {
// return name.hashCode() + age.hashCode() + salary.hashCode();
return Objects.hash(name, age, salary);
}
}
class Student{
String name;
Integer age;
Double score;
@Override
public int hashCode(){
return name.hashCode() + age.hashCode() + score.hashCode();
}
@Override
public boolean equals(Object o) {
System.out.println("Student.equals");
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return Objects.equals(name, student.name) && Objects.equals(age, student.age) && Objects.equals(score, student.score);
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
public Student(String name, Integer age, Double score) {
this.name = name;
this.age = age;
this.score = score;
}
}
1.1.2 LinkedHashSet
- 特点:可以获取元素时维护插入的顺序,存入对象时依然无序LinkedHashSet会记录每个元素插入的顺序,获取元素时按照顺序获取。
1.2 Map接口
- 特点:一个元素由两个对象构成,key键与value值,通过key操作value。
无序、无下标、键不可重复、值可以重复。 - 比如:
key value 张 -----> zhang 李 -----> li 里 -----> li 单 -----> dan,shan
1.2.1 常用方法
- 比如:
方法名 作用 put(K key , V value) 向Map添加一组键值对,如果键已存在则覆盖 remove(K key) 根据key删除一组键值对 get(K key) 根据key获取一个value clear() 清空 containsKey(Object key) 判断key是否存在 containsValue(Object value) 判断value是否存在 size() 返回键值对数量 keySet() 获取所有的键,返回值为Set values() 获取所有的值,返回值为Collection entrySet() 返回所有的entry(键值对),返回值为Set
1.2.2 Map集合的遍历
- 键遍历(常用)。
获取所有的键。Map<Integer,String> map = new HashMap<>(); // 键遍历,获取所有的键 Set<Integer> keys = map.keySet(); // 遍历keys获取每一个键 for (Integer key : keys) { System.out.print( key+" ------- " ); // 利用key获取value String value = map.get( key ); System.out.println(value); }
- 值遍历(了解)。
获取所有的值。
Map<Integer,String> map = new HashMap<>(); // 值遍历 // 获取所有的value Collection<String> values = map.values(); // 遍历 for (String value : values) { System.out.println( value ); }
- 值遍历(了解)。
- 键值遍历。
获取所有的键值对。Map<Integer,String> map = new HashMap<>(); // 获取所有的键值对 // 获取所有的Map.Entry Set<Map.Entry<Integer,String>> entrys = map.entrySet(); // 遍历set集合获取每个Map.Entry for(Map.Entry<Integer,String> entry : entrys ){ Integer key = entry.getKey();//获取key String value = entry.getValue();//获取value System.out.println(key+" ----- "+value); }
1.3 实现类
- HashMap
特点:操作速度快,线程不安全,如果key为自定义类型必须覆盖hashCode与equals。 - Hashtable(用不着)
特点:操作速度慢,线程安全。 - LinkedHashMap
特点:操作速度快,线程不安全,可以维护插入顺序。
演示的代码如下:
package com.txw.test;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class TestMap {
public static void main(String[] args) {
// key泛型 value泛型
Map<Integer,String> map = new HashMap<>();
// 学号(Integer)与学生姓名(String)
map.put(8848,"阿森");
map.put(1101,"阿云");
map.put(1102,"阿伟");
map.put(1103,"阿黄");
// 根据学号查询学生姓名
String name1 = map.get(1103);
// System.out.println(name1);
// 删除学号为8848的劣质学生
map.remove(8848);
// 查看键值对数量
// System.out.println(map.size());
// 如果key已存在则替换
map.put(1101,"阿森");
// System.out.println( map.get(1101) );
// 查看有没有学号为1104的学生
// System.out.println( map.containsKey(1104) );
// 查看有没有叫阿森的学生
// System.out.println( map.containsValue("阿森") );
// Map<Integer,String> map = new HashMap<>();
// 键遍历,获取所有的键
/* Set<Integer> keys = map.keySet();
// 遍历keys获取每一个键
for (Integer key : keys) {
System.out.print( key+" ------- " );
// 利用key获取value
String value = map.get( key );
System.out.println(value);
}*/
// 值遍历
// 获取所有的value
// Collection<String> values = map.values();
// 遍历
// for (String value : values) {
// System.out.println( value );
// }
// 获取所有的键值对
// 获取所有的Map.Entry
Set<Map.Entry<Integer,String>> entrys = map.entrySet();
// 遍历set集合获取每个Map.Entry
for(Map.Entry<Integer,String> entry : entrys ){
Integer key = entry.getKey(); // 获取key
String value = entry.getValue(); // 获取value
System.out.println(key+" ----- "+value);
}
}
}
总解
1 List
- 特点:有序、有下标、可重复。
- 常用方法(增删改查):
1. add(Object o ) , add(int index , Object o) 添加元素 2. remove(Object o) , remove(int index ) 删除元素 3. set(int index , Object o) 修改元素 4. get(int index) 或 遍历 查看元素
- 实现类:
1. ArrayList 数组实现,查询快,增删慢,操作速度快,线程不安全。 2. LinkedList 链表实现,查询慢,增删快,操作速度快,线程不安全。
2 Set
- 特点:无序、无下标、不可重复。
- 常用方法(增删改查):
1. add(Object o) 添加元素 2. remove(Object o) 删除元素 改不了 遍历 查看元素
- 实现类
-
1. HashSet 操作速度快,线程不安全,实现方式 数组+链表,链表过长会转换为红黑树, 使用对象的hashCode与equals方法过滤重复,务必保证存入的对象为自定义类型时,必须手动覆盖hashCode与equals否则无法过滤重复。 2. LinkedHashSet 操作速度快,线程不安全,去重机制与HashSet一致 。
3 Map
- 特点:无序,无下标,key不可以重复,value可以重复。
内部的元素都是由key与value两个对象组成。 - 常用方法(增删改查):
1. put(K key,V value) 添加元素 2. remove(K key ) 删除元素 3. put(K key, V value) 修改元素(如果元素以存在则替换) 4. get(K key) 查看元素(根据key获取value) 键遍历 值遍历 键值遍历
- 实现类
1. HashMap 操作速度快,线程不安全,key不可以重复,使用key对象的hashCode与equals过滤重复,如果key为自定义类型,务必保证覆盖hashCode与equals两个方法,否则无法过滤重复。 2. LinkedHashMap 操作速度快,线程不安全,可以维护元素的插入顺序
如图所示: