个人整理非商业用途,欢迎探讨与指正!!
« 上一篇
Set集合是如何判断数据不能重复?
先判断hashCode再判断equals方法
首先比较两个对象的hashCode值,若值不一样则是两个不同的对象;若hashCode值一样,那么就会去比较equals方法,若equals方法false,则表示两个不同的对象,在Set集合中就不算重复了
若只重写一个,可能导致数据添加的准确
只重写hashCode,没有重写equals,对象的内容相同了,hashCode就一样了,但没有重写equals数据也添加了
只重写了equals,若hashCode不一致,则直接判断为两个不同的对象
package com.qf.test01;
import java.util.HashSet;
import java.util.Set;
public class Demo11 {
// 首先比较两个对象的hashCode值,若值不一样则是两个不同的对象;
// 若hashCode值一样,那么就会去比较equals方法,
// 若equals方法false,则表示两个不同的对象,在Set集合中就不算重复了
public static void main(String[] args) {
Set<Dog> set = new HashSet<>();
// 1.Dog类中没有重写hashCode和equals方法时,
// 两个对象的内容完全一样但是没有重写,被判断为两个对象,
// 能看见重复的数据添加到Set中
/*set.add(new Dog(1,"大黄",2,"玩"));
set.add(new Dog(1,"大黄",2,"玩"));
System.out.println(set);*/
// 2.Dog类中重写hashCode和equals方法
// 重写时:hashCode返回一个固定的 equals返回true
// 添加两个内容相同的对象,被判断为同一个对象
/*set.add(new Dog(1,"大黄",2,"玩"));
set.add(new Dog(1,"大黄",2,"玩"));
set.add(new Dog(1,"大黄",2,"玩"));
System.out.println(set);*/
// 3.Dog类中重写hashCode和equals方法
// 重写时:hashCode返回一个固定的 equals返回false
/*set.add(new Dog(1,"大黄",2,"玩"));
set.add(new Dog(1,"大黄",2,"玩"));
set.add(new Dog(1,"大黄",2,"玩"));
set.add(new Dog(1,"大黄",2,"玩"));
System.out.println(set);
System.out.println("-----------------");*/
// 因为编码比较极端,hashCode是0 equals是true,
// 意味着Dog的所有对象,都一样
/*set.add(new Dog());
set.add(new Dog(2,"123",3,"嘿嘿"));
set.add(new Dog());
System.out.println(set);*/
// 4.只重写了equals方法,hashCode是第一被调用的方法
set.add(new Dog(1,"大黄",2,"玩"));
set.add(new Dog(1,"大黄",2,"玩"));
set.add(new Dog(1,"大黄",2,"玩"));
System.out.println(set);
}
}
// 伪代码
class Dog{
@Override
public int hashCode() {
System.out.println("hashCode被调用");
return 0;
}
@Override
public boolean equals(Object obj) {
System.out.println("equals被调用");
return true;
}
}
是HashSet的子类
特点:
有序,无下标,不重复,去重复原理和父类一样
public class Demo12 {
public static void main(String[] args) {
LinkedHashSet<String> set = new LinkedHashSet<>();
set.add("张三");
set.add("李四");
set.add("王五");
set.add("赵六");
set.add("赵六");
// 添加和存放顺序是一样的Set集合
System.out.println(set);
}
}
1.迭代器
2.foreach循环
public class Demo13 {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("zs");
set.add("ls");
set.add("ww");
set.add("zl");
// 使用迭代器 jdk1.5之前
Iterator<String> it = set.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
System.out.println("-------------------------");
// foreach jdk1.5之后
for (String string : set) {
System.out.println(string);
}
}
}
底层使用红黑树实现的
特点:
无序(有字典顺序),无下标,不可重复
使用TreeSet存储的对象必须实现Comparable接口
Comparable接口:用于定义排序方法和去重
接口中方法:compareTo方法
返回值是大于0的数升序的,返回值是小于0的数降序的,若等于0被认为是同一个对象
public class Demo14 {
public static void main(String[] args) {
TreeSet<Integer> set = new TreeSet<>();
set.add(1);
set.add(8);
set.add(20);
set.add(3);
set.add(7);
set.add(5);
// 重复的值是不能添加进入TreeSet集合
set.add(5);
// 不能添加空值
// set.add(null);
// 排序之后进行存放(字典顺序)
System.out.println(set);
}
}
可以添加到TreeSet集合中元素,必须实现Comparable接口
TreeSet集合在去重时,会调用compareTo方法
作用:
1.排序:大于0升序(向当前位置的元素之后添加新的元素),小于0降序(向当前位置元素之前添加新的元素)
2.去重:等于0时,当前位置的元素和新的元素比较的没结果,将无法加入到当前集合中
public class Pig implements Comparable<Pig>{
String name;
int age;
public Pig(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Pig() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "Pig [name=" + name + ", age=" + age + "]";
}
// 自定义去重规则
@Override
public int compareTo(Pig o) {
System.out.println("compareTo()");
return -1;
}
}
public class Demo15 {
public static void main(String[] args) {
TreeSet<Pig> set = new TreeSet<>();
// 1.添加的对象没有实现Comparable接口,可以添加但是无法运行成功
/*set.add(new Pig("佩奇",10));
set.add(new Pig("乔治",9));
System.out.println(set);*/
// 2.Pig实现了Comparable接口
// compareTo方法返回值为0,当前方法是比较时才会调用
// 结果为0时,认定为重复数据
// 返回值为1(大于0) 是新数据比当前数据位置要靠后
// 返回值为-1(小于0) 是新数据比当前数据位置靠前
// compareTo决定了TreeSet集合中数据存放的位置
set.add(new Pig("佩奇",10));
System.out.println("---");
set.add(new Pig("乔治",9));//和已经存在的第一个元素进行了比较
System.out.println("---");
set.add(new Pig("乔治",10));//和之前的两个数据进行比较
System.out.println("---");
System.out.println(set);
}
}
public class Animal implements Comparable<Animal>{
String name;
int age;
@Override
public String toString() {
return "Animal [name=" + name + ", age=" + age + "]";
}
public Animal(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Animal() {
super();
// TODO Auto-generated constructor stub
}
// 自定义排序方式 当前对象的age属性和参数的age属性进行比较,若差值大于0升序 否则降序 为0是无法加入
@Override
public int compareTo(Animal o) {
System.out.println("compareTo:"+o);
// 使用年龄定义的方案
return age - o.age;
}
public static void main(String[] args) {
TreeSet<Animal> set = new TreeSet<>();
// 使用年龄进行计算
set.add(new Animal("AA", 10));
System.out.println("--------------");
set.add(new Animal("BB", 9));
System.out.println("--------------");
set.add(new Animal("CC", 11));
System.out.println("--------------");
set.add(new Animal("DD", 12));
System.out.println("--------------");
System.out.println(set);
}
}
单列集合的工具类,都是静态方法
public class Demo16 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("2");
list.add("1");
list.add("4");
list.add("3");
list.add("5");
System.out.println(list);
// 进行排序
Collections.sort(list);
System.out.println(list);
// 反转集合
Collections.reverse(list);
System.out.println(list);
// 随机打乱
Collections.shuffle(list);
System.out.println(list);
}
}
特点:
双泛型接口
Map
Map使用键(Key)和值(Value)组成的键值对
Key:无序的,不重复,无下标(Set集合实现的)
Value:无序,可重复,无下标(Collection集合实现的)
public class Demo01 {
public static void main(String[] args) {
// 在后续的编程中,KV结构是非常多的
Map<String,Object> map = new HashMap<>();
// 添加集合方法
map.put("A", 10);//Integer
map.put("B", "BaiBai");
map.put("C", 100.02);//Double
map.put("D", false);//Boolean
System.out.println(map);
// 获取 通过K或者V
System.out.println(map.get("A"));
System.out.println(map.get("E"));//null
// 清空
/*map.clear();
System.out.println(map);*/
// 判断是否有内容
System.out.println(map.isEmpty());
// Key是否存在
System.out.println(map.containsKey("A"));
// Value是否存在
System.out.println(map.containsValue(10));
// 获取所有的Key的Set集合
System.out.println(map.keySet());
// 获取所有的Value的Collecion集合
System.out.println(map.values());
// Map的有效数据个数
System.out.println(map.size());
// 通过Key移除K-V数据
map.remove("A");
System.out.println(map);
}
}
常用方法:略
使用红黑树+链表的数据结构
可以使用Map
可以使用List
// 封装一个商品实体:商品编号,名称,价格,产地,上架时间...
public class Goods {
private int id;
private String name;
private double price;
public Goods(int id, String name, double price) {
super();
this.id = id;
this.name = name;
this.price = price;
}
@Override
public String toString() {
return "Goods [id=" + id + ", name=" + name + ", price=" + price + "]";
}
public static void main(String[] args) {
// 单个商品:创建商品对象
Goods g1 = new Goods(1, "黑人牙膏", 10.8);
Goods g2 = new Goods(1, "黑人牙膏", 10.8);
Goods g3 = new Goods(1, "黑人牙膏", 10.8);
Goods g4 = new Goods(1, "黑人牙膏", 10.8);
// 多件商品:多个对象同时携带,将上述的四件商品添加到集合中
ArrayList<Goods> gs = new ArrayList<>();
gs.add(g1);
gs.add(g2);
gs.add(g3);
gs.add(g4);
}
}
// 使用map封装实体数据
// 使用map集合和完成和实例类相似的功能
// 单个商品:和实例类中的数据显示是一样的
HashMap<String,Object> goods1 = new HashMap<>();
goods1.put("id", 1);
goods1.put("name", "黑人药膏");
goods1.put("price", 10.8);
System.out.println(goods1);
HashMap<String,Object> goods2 = new HashMap<>();
goods2.put("id", 2);
goods2.put("name", "白人药膏");
goods2.put("price", 10.8);
System.out.println(goods2);
// 多个商品:使用List集合存放Map
ArrayList<HashMap<String,Object>> ggs = new ArrayList<>();
ggs.add(goods1);
ggs.add(goods2);
System.out.println(ggs);
public class Test01 {
// 使用集合存放省市数据
// ["辽宁":{"沈阳","大连","鞍山"},"吉林":{"四平","长春"}]
public static void main(String[] args) {
// K为String V为List集合
HashMap<String,List<String>> map = new HashMap<>();
List<String> city1 = new ArrayList<>();
city1.add("沈阳");
city1.add("大连");
city1.add("鞍山");
// 添加到map中
map.put("辽宁", city1);
List<String> city2 = new ArrayList<>();
city2.add("四平");
city2.add("长春");
map.put("吉林", city2);
System.out.println(map);
}
}
常用方法和HashMap一致
Hashtable是线程安全的,HashMap是线程不安全的
Hashtable不允许存储null作为K和V的,HashMap可以
public class Demo04 {
public static void main(String[] args) {
Hashtable<String,Object> map = new Hashtable<>();
map.put("A", "A");
map.put("B", "B");
map.put("C", "C");
map.put("D", "D");
// 为同一个key赋值 k是可重复的
map.put("A", "AA");
// Hashtable中是不能存在null值的
// map.put(null, "EE");
// map.put("E", null);
System.out.println(map);
}
}
语法:
类名
public class Box<T> {//T:表示任意的java类型 E,K,V...
private T data;//可以作为引用存在 但是不能使用T创建对象
// 为T进行初始化
public void setData(T data) {
this.data = data;
}
// 返回T的实例/对象
public T getData() {
return data;
}
public static void main(String[] args) {
Box<String> box = new Box<>();
box.setData("hello");
System.out.println(box.getData());
Box<Integer> b1 = new Box<>();
b1.setData(10);
System.out.println(b1.getData());
}
}
语法:
接口名
public interface MyInterface<T> {
void show(T t);
}
class My implements MyInterface<String> {
@Override
public void show(String t) {
// 对t进行操作
}
}
语法:
public T 方法名(T t,…){}
public class Store {
// 泛型可以作为参数,必须在当前方法中先定义
public <E> void m1(E e) {
}
public <V> V get(V v) {
return v;
}
}
public class Demo01 {
// 泛型上下边界
/**
* 不能确定好泛型的类型时,可以使用?
* @param list
*/
public static void test01(List<?> list) {}
/**
* 定义上边界
* extends 类型>
* 传递泛型时,可以是类型及其子类
* @param args
*/
public static void test02(List<? extends Number> list) {}
/**
* 定义下边界
* super 类型>
* 传递泛型时,可以是类型及其父类
* @param args
*/
public static void test03(List<? super Number> list) {}
public static void main(String[] args) {
test01(new ArrayList<Integer>());
test01(new ArrayList<String>());
test02(new ArrayList<Number>());
test02(new ArrayList<Integer>());
test02(new ArrayList<Double>());
// test02(new ArrayList
test03(new ArrayList<Number>());
// test03(new ArrayList());
test03(new ArrayList<Object>());
}
}