集合框架之set
1.集合框架set集合框架Set(HashSet哈希表存储、重复元素存储底层探究)
1.set基础知识
set集合不能存放重复元素(只限对于字符串、八大基本数据类型)set集合中的元素是无序的(存入和取出的顺序不一定一致)
测试如下:
package com.wangcong.set;
import java.util.HashSet;
import java.util.Set;
public class SetTest {
public static void main(String[] args) {
Set set=new HashSet<>();
set.add("ni");
set.add("wo");
set.add("ta");
set.add("ni");//此次与第一条add数据一致
System.out.println(set.size());
}
}
运行结果为3。由此可看出set集合不能存放重复元素
运行如下代码:
package com.wangcong.set;
import java.util.HashSet;
import java.util.Set;
public class SetTest {
public static void main(String[] args) {
Set set=new HashSet<>();
set.add(new Person("wanting", 18, 1500));
set.add(new Person("zhuangyuan", 23, 500));
set.add(new Person("runchen", 19, 1200));
set.add(new Person("xiang", 22, 2500));
set.add(new Person("wanting", 18, 1500));//此处数据与第一条数据一样
System.out.println(set.size());
}
}
//定义Person类
class Person{
private String name;
private int age;
private int money;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", money=" + money + "]";
}
public Person(String name, int age, int money) {
super();
this.name = name;
this.age = age;
this.money = money;
}
public Person() {
super();
}
}
控制台打印结果为5。说明set重复只限于只限对于字符串、八大基本数据类型
测试如下代码:
package com.wangcong.set;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class SetTest {
public static void main(String[] args) {
Set set=new HashSet<>();
set.add(new Person("wanting", 18, 1500));
set.add(new Person("zhuangyuan", 23, 500));
set.add(new Person("runchen", 19, 1200));
set.add(new Person("xiang", 22, 2500));
set.add(new Person("wanting", 18, 1500));//此处数据与第一条数据一样
//System.out.println(set.size());
Iterator it=set.iterator();//定义一个迭代器
while(it.hasNext()) {
System.out.println(it.next());
}
}
}
//定义Person类
class Person{
private String name;
private int age;
private int money;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", money=" + money + "]";
}
public Person(String name, int age, int money) {
super();
this.name = name;
this.age = age;
this.money = money;
}
public Person() {
super();
}
}
打印结果如图:
可以看出:set集合中的元素是无序的(存入和取出的顺序不一定一致)
1.2 重复元素存储底层探究
HashSet是如何保证元素唯一性的呢?
思路:
是通过元素的两个方法:hashCode与equals方法来完成;如果hashCode值相同,才会判断equals是否为true;如果hashCode值不同,那么不会调用equals。
package com.wangcong.set;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class SetTest {
public static void main(String[] args) {
Set set=new HashSet<>();
set.add(new Person("wanting", 18, 1500));
set.add(new Person("zhuangyuan", 23, 500));
set.add(new Person("runchen", 19, 1200));
set.add(new Person("xiang", 22, 2500));
set.add(new Person("wanting", 18, 1500));//此处数据与第一条数据一样
System.out.println(set.size());
Iterator it=set.iterator();//定义一个迭代器
while(it.hasNext()) {
System.out.println(it.next());
}
}
}
//定义Person类
class Person{
private String name;
private int age;
private int money;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", money=" + money + "]";
}
public Person(String name, int age, int money) {
super();
this.name = name;
this.age = age;
this.money = money;
}
public Person() {
super();
}
@Override
public int hashCode() {
System.out.println("hashCode---------"+this.name);
int code=this.name.hashCode()+this.age;//算一个name和age的哈希码值的和
System.out.println(code);
return code;
}
@Override
public boolean equals(Object obj) {
System.out.println("equals---");
Person p=(Person)obj;
return this.name.equals(p.name) && this.age==p.age;
}
}
2、集合框架TreeSet(自然排序、数据结构二叉树、比较器排序)
2.1自然排序
运行如下代码:
package com.wangcong.set;
import java.util.TreeSet;
public class TreeSetTest {
public static void main(String[] args) {
TreeSet set=new TreeSet<>();
set.add(25);
set.add(23);
set.add(31);
set.add(28);
System.out.println(set);
}
}
运行结果如下:
2.1.2
运行如下代码:
public class TreeSetTest {
public static void main(String[] args) {
TreeSet set=new TreeSet<>();
// set.add(25);
// set.add(23);
// set.add(31);
// set.add(28);
set.add("abc");
set.add("be");
set.add("dc");
set.add("geg");
set.add("ge");
System.out.println(set);
}
}
输入结果为:
2.2数据结构二叉树
什么是二叉树:treeSet容器是根据二叉树的排序规则对容器中元素进行排序的 自然排序(元素自身具有比较性)
package com.wangcong.set;
import java.util.Iterator;
import java.util.TreeSet;
/**
* 2.集合框架TreeSet(自然排序.数据结构二叉数。比较器排序)
* 1.treeSet容器是根据二叉数的排序规则对容器中元素进行排序的 自然排序(元素自身具有比较性)
* @author wangcong
*
*/
public class TreeSetTest {
public static void main(String[] args) {
TreeSet set=new TreeSet<>();
set.add(new Person("wanting", 18, 1500));
set.add(new Person("zhuangyuan", 23, 500));
set.add(new Person("runchen", 19, 1200));
set.add(new Person("xiang", 22, 2500));
set.add(new Person("wantings", 88, 1500));
// System.out.println(set);
Iterator it = set.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
}
//定义Person类
class Person implements Comparable<Person>{
private String name;
private int age;
private int money;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", money=" + money + "]";
}
public Person(String name, int age, int money) {
super();
this.name = name;
this.age = age;
this.money = money;
}
public Person() {
super();
}
@Override
public int hashCode() {
System.out.println("hashCode---------"+this.name);
int code=this.name.hashCode()+this.age;//算一个name和age的哈希码值的和
System.out.println(code);
return code;
}
@Override
public boolean equals(Object obj) {
System.out.println("equals---");
Person p=(Person)obj;
return this.name.equals(p.name) && this.age==p.age;
}
/**
*
* 让元素具有比较性
*
* 注意:在做自然排序方法重写的时候,一定要先判断主要条件,还要判断次要条件
*
*/
@Override
public int compareTo(Person o){
int num=o.money-this.money;
if(num==0) {
return o.age-this.age;
}
return num;
}
}
2.3 比较器排序(用于应对某些代码频繁修改所带来不便情况)
通过实现Comparator来完成(调用不同的方法来完成)不需要每次都修改代码,也可以实现方法回滚
package com.wangcong.set;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
/**
* 2.集合框架TreeSet(自然排序.数据结构二叉数。比较器排序)
* 1.treeSet容器是根据二叉数的排序规则对容器中元素进行排序的 自然排序(元素自身具有比较性)
* @author wangcong
*
*/
public class TreeSetTest {
public static void main(String[] args) {
// TreeSet set=new TreeSet<>();
// TreeSet<Person> set=new TreeSet<>(new Personba());
TreeSet<Person> set=new TreeSet<>(new Personjiu());
set.add(new Person("wanting", 18, 1500));
set.add(new Person("zhuangyuan", 18, 500));
set.add(new Person("runchen", 19, 1200));
set.add(new Person("xiang", 22, 2500));
set.add(new Person("wantings", 88, 1500));
// System.out.println(set);
Iterator it = set.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
}
/**
* 年小钱多
* @author wangcong
*
*/
class Personba implements Comparator<Person>{
public int compare(Person o1, Person o2) {
int num=o1.getAge()-o2.getAge();//主要条件年少
if(num==0) {
return o2.getMoney()-o1.getMoney();//次要钱多
}
return num;
}
}
/**
* 多钱年轻
* @author wangcong
*
*/
class Personjiu implements Comparator<Person>{
public int compare(Person o1, Person o2) {
int num=o2.getMoney()-o1.getMoney();//主要条件钱多
if(num==0) {
return o1.getAge()-o2.getAge();//次要年少
}
return num;
}
}
//定义Person类
class Person implements Comparable<Person>{
private String name;
private int age;
private int money;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", money=" + money + "]";
}
public Person(String name, int age, int money) {
super();
this.name = name;
this.age = age;
this.money = money;
}
public Person() {
super();
}
@Override
public int hashCode() {
System.out.println("hashCode---------"+this.name);
int code=this.name.hashCode()+this.age;//算一个name和age的哈希码值的和
System.out.println(code);
return code;
}
@Override
public boolean equals(Object obj) {
System.out.println("equals---");
Person p=(Person)obj;
return this.name.equals(p.name) && this.age==p.age;
}
/**
* 让元素具有比较性
* 注意:在做自然排序方法重写的时候,一定要先判断主要条件,还要判断次要条件
*/
@Override
public int compareTo(Person o){
int num=o.money-this.money;
if(num==0) {
return o.age-this.age;
}
return num;
}
}
3、泛型
3.1泛型是什么?有什么好处?
不使用泛型的情况下,会将未知的错误表现在运行期
如果说用代码去处理了这个可能发现的错误,那么运行时期的错误就不会暴露出来
泛型的好处:
1.将运行期的异常转换成编译期的错误,让程序员更早的发现,从而解决代码隐患
2.提高了代码的健壮性
3.2
package com.wangcong.set;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
*
* @author wangcong
*
*/
public class FanXinTest {
public static void main(String[] args) {
List c=new ArrayList<>();
c.add(23);
c.add(25);
c.add(26);
c.add(28);
c.add(55);
Iterator it = c.iterator();
while(it.hasNext()) {
Object obj=it.next();
if(obj instanceof Integer) {
int num=(int) obj;
if(num %2 == 0) {
System.out.println(num);
}
}
}
}
}
/*
* --------不使用泛型的情况-----------------
* 购物车项目
* 订单模块,用户模块、商品模块
* Class OrderDao{
* public List<Order> list(Order order){
*
* }
*
* public int add(Order order){}
* public int edit(Order order){}
* public int del(Order order){}
*
* }
*
* Class UserDao{
* public List<User> list(User User){}
* public int add(User User){}
* public int edit(User User){}
* public int del(User User){}
*
* }
*
* Class ProductDao{
*
* }
*
* --------使用泛型的情况-----------------
* Class BaseDao<T>{
* public List<T> list(T t){}
* public int add(T t){}
* public int edit(T t){}
* public int del(T t){}
* }
*
* Class OrderDao extends BaseDao<Order>{}
* Class UserDao extends BaseDao<User>{}
* Class ProductDao extends BaseDao<Product>{}
*/
总的来说,泛型在代码量上减少了一下重复的代码,减少了开发所用的重复的时间,不需要重复写代码,只需要传入不同的类型就可以简化代码