1.Collection 接口下面的方法
add()
addAll()
remove(Object obj);
removeAll();
clear();
size();
contains();
toArray();
conatinsAll();
isEmpty();
2.List接口的方法
add(int index, E e);
addAll(int index, Collection<? extends E>);
remove(int index);
set(int index, E e);
get(int index);
indexOf(E e);
lastIndexOf(E e);
subList(int fromIndex, int toIndex);
3.static关键字的使用
static 修饰成员变量
static修饰成员方法
static修饰代码块
4.throw和throws的区别
throw 抛出一个异常对象
throws 在方法的声明处使用,告知调用者此方法有异常
5.接口和抽象类的区别
接口声明interface
抽象类abstract
6.ArrayList和LinkedList的区别
回顾
1.Collection的方法
2.对集合遍历
1.for循环
2.增强for循环
3.迭代器
3.List接口下面的方法
4.ArrayList和LinkedList的区别
5.集合中存对象的
1.Object类
2.Set集合
3.匿名内部类
4.map集合
Object类是Java中所有类的基类
学习Object类就是在学习他的方法
构造方法:
可以直接实例化
Object()
只需要学习三个方法
String
toString()
返回对象的字符串表示形式
public String toString()
返回对象的字符串表示形式。 一般来说,
toString
方法返回一个“textually代表”这个对象的字符串。 结果应该是一个简明扼要的表达,容易让人阅读。 建议所有子类覆盖此方法。该
toString
类方法Object
返回一个由其中的对象是一个实例,该符号字符的类的名称的字符串
@` ”和对象的哈希码(内存地址)的无符号的十六进制表示。 换句话说,这个方法返回一个等于下列值的字符串:getClass().getName() + '@' + Integer.toHexString(hashCode())
结果
对象的字符串表示形式。
package com.qfedu.a_object;
class Person {
String name;
int age;
//person类是Object类子类不? 是!!!
//
@Override
public String toString() {
System.out.println("123");
return
"name=\"" + name + '\"' +
", age=" + age
;
}
}
public class Demo1 {
public static void main(String[] args) {
Object obj = new Object();
Person person = new Person();
System.out.println(person);
}
}
boolean
equals(Object obj)
指示一些其他对象是否等于此。
boolean eaqual(Object obj);
public boolean equals(Object obj) { return (this == obj); }
Object 类下面的方法比较是两个对象的地址。不看内容的
为啥String类下面的equals方法比较的是内容呢?String类继承了Object
equals方法重写了Object类下面的。为啥重写?
当父类的需求,满足不了子类的需求的时候要重写父类的方法
需求:比较两个对象的内容是否一样? 如果两个对象的内容一样返回一个true。反之返回false
package com.qfedu.a_object;
import java.util.Objects;
class Student {
String name;
int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
//重写equlas,要求去比较内容,如果内容一样的额话,返回true
//stu1.equals(stu2)
//stu2赋值给了 o 向上转型 Object o =new Student();
@Override
public boolean equals(Object o) {
if (this == o) {//比较是地址
return true;
}
//如果地址不一样的话,再去比较内容,如果内容一样也返回true
if (o instanceof Student) {
//才去比较值 name age
Student stu = (Student)o;//向下转型
//stu1.equals(stu2) stu就是stu2 this 是stu1
return stu.age == this.age && stu.name.equals(this.name);
}
return false;
}
}
public class Demo2 {
public static void main(String[] args) {
Student stu1 = new Student("老邢", 89);
Student stu2 = new Student("老邢", 89);
//stu1是Object类子类,用的是object 类面的equals方法
//Object类下面的equals方法比较是 地址 this==obj
//System.out.println(stu1.equals(stu2));//false
//现在我的需求是当两个对象的内容一致的时候返回的额是true
//内容不一样的时候,返回是false
//就意味着Object类的equals方法已经满足不了Student类的需求了
//咋解决? 重写equals方法
System.out.println(stu1.equals(stu2));//true
}
}
package com.qfedu.a_object;
import java.util.Objects;
class Student1 {
String name;
int age;
public Student1(String name, int age) {
this.name = name;
this.age = age;
}
//重写equlas,要求去比较内容,如果内容一样的额话,返回true
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || this.getClass() != o.getClass()){
return false;
}
Student1 student1 = (Student1) o;
return age == student1.age && Objects.equals(name, student1.name);
}
}
public class Demo3 {
public static void main(String[] args) {
Student1 stu1 = new Student1("老邢", 89);
Student1 stu2 = new Student1("老邢", 89);
//stu1是Object类子类,用的是object 类面的equals方法
//Object类下面的equals方法比较是 地址 this==obj
//System.out.println(stu1.equals(stu2));//false
//现在我的需求是当两个对象的内容一致的时候返回的额是true
//内容不一样的时候,返回是false
//就意味着Object类的equals方法已经满足不了Student1类的需求了
//咋解决? 重写equals方法
System.out.println(stu1.equals(stu2));//true
}
}
int hashCode();
哈希码值:在Object类下面,将内存地址(十六进制的值)转为十进制的值,此时这个十进制的值就叫hash码。
返回对象的哈希码值。 支持这种方法是为了散列表,如
HashMap
提供的那样 。
hashCode
的注意事项是:
- 只要在执行Java应用程序时多次在同一个对象上调用该方法,
hashCode
方法必须始终返回相同的整数,前提是修改了对象中equals
比较中的信息。 该整数不需要从一个应用程序的执行到相同应用程序的另一个执行保持一致。- 如果根据
equals(Object)
方法两个对象相等,则在两个对象中的每个对象上调用hashCode
方法必须产生相同的整数结果。- 不要求如果两个对象根据
equals(java.lang.Object)
方法不相等,那么在两个对象中的每个对象上调用hashCode
方法必须产生不同的整数结果。 但是,程序员应该意识到,为不等对象生成不同的整数结果可能会提高哈希表的性能。尽可能多的合理实用,由类别
Object
定义的hashCode方法确实为不同对象返回不同的整数。 (hash码的值通常通过将对象的内部地址转换为整数来实现,但Java的编程语言不需要此实现技术。)
package com.qfedu.a_object;
class Cat {}
public class Demo4 {
public static void main(String[] args) {
Cat cat1 = new Cat();
Cat cat2 = new Cat();
System.out.println(cat1.hashCode());
System.out.println(cat2.hashCode());
String str = new String("a");
String str1 = new String("b");
String str2 = new String("a");
//现在真他娘的尴尬,Object类的hash值是内存地址十进制的转换
//只要你内U存地址不一样,hash值一定不一样
//但是你看看str和str2 ,内存地址不一样,但是
//hash值是一样的?咋回事?在String类中重写了hashCode
//方法
System.out.println(str.hashCode());//97
System.out.println(str1.hashCode());//98
System.out.println(str2.hashCode());//97
}
}
请注意,无论何时重写equals方法,通常需要重写
hashCode
方法,以便维护hashCode
方法的通用合同,该方法规定相等的对象必须具有相等的哈希码
package com.qfedu.a_object;
import java.util.Objects;
class Dog {
int id;
String name;
public Dog(int id, String name) {
this.id = id;
this.name = name;
}
public boolean equals (Object o) {
if (this == o) {
return true;
}
if (o instanceof Dog) {
Dog dog = (Dog)o;
return this.id == dog.id && dog.name.equals(this.name);
}
return false;
}
@Override
public int hashCode() {
return name.hashCode() + id;
}
}
public class Demo5 {
public static void main(String[] args) {
Dog dog1 = new Dog( 3, "a");
Dog dog2 = new Dog( 2, "b");
//现在关注的是内容,如果内容一样 调用equals方法的时候
//必须返回一个true
System.out.println(dog1.equals(dog2));//true
//此时这个两个对象的hash值一样不一样?因为内存地址不一样的
System.out.println(dog1.hashCode());
System.out.println(dog2.hashCode());
//现在hashCode不一样咋办? 重写hashCode即可
//如果根据equals(Object)方法两个对象相等,
// 则在两个对象中的每个对象上调用hashCode方法必须产生相同的整数结果。
//如果两个对象的hash值一样,对象是不一定一样的。但是如果两个对象相等
//那么hash值一定相等
}
}
package com.qfedu.a_object;
import java.util.Objects;
class Panda {
int id;
String name;
public Panda(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Panda panda = (Panda) o;
return id == panda.id && Objects.equals(name, panda.name);
}
@Override
public int hashCode() {
return id;
}
}
public class Demo6 {
public static void main(String[] args) {
String str1 = new String("ab");
String str2 = new String("a");
System.out.println(str1.equals(str2));//true
//31 * 97+ 98
System.out.println(str1.hashCode());//3105
System.out.println(str2.hashCode());
//STring类下面的hashCode重写的Object类下面的
Integer i1 = new Integer(45);
Integer i2 = new Integer(45);
System.out.println(i1 == i2);//false
System.out.println(i1.equals(i2));//true
//大胆猜测一下 hash值是啥?
System.out.println(i1.hashCode());
System.out.println(i2.hashCode());
Panda panda1 = new Panda(67, "狗蛋");
Panda panda2 = new Panda(67, "狗蛋");
System.out.println(panda2.equals(panda1));
System.out.println(panda1.hashCode());
System.out.println(panda2.hashCode());
}
}
回顾一下
1.toString方法
2.equals方法
3.hashCode方法
这个三个方法都可以有快捷键
Set集合也是用来存储数据的
Set也是一个接口
父接口是Collection
存储数据的特征: 无序的 不可重复的
Set接口有两个实现类:
? HashSet:
? 依靠hash值进行存储的,如果两个元素hash值一样的话,就不再存储了
? TreeSet:
? 底层是二叉树,对存储数据进行自然排序
HashSet这个类的方法和Collection接口和Set接口下面一样的
也有自己独有的方法,和ArrayList特别象
package com.qfedu.b_hashSet;
import java.util.HashSet;
import java.util.Set;
public class Demo1 {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
//set集合存储的无序的 不可重复的
set.add("b");
set.add("a");
set.add("d");
set.add("c");
set.add("a");
set.add("ad");
System.out.println(set);
Set<Integer> set1 = new HashSet<>();
set1.add(78);
set1.add(23);
set1.add(100);
set1.add(56);
System.out.println(set1);
set1.remove(23);
//循环
for (Integer integer : set1) {
System.out.println(integer);
}
}
}
package com.qfedu.b_hashSet;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
class Person {
int id;
String name;
public Person(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return id == person.id && Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
public class Demo2 {
public static void main(String[] args) {
Person person1 = new Person(1, "zhangsan");
Person person2 = new Person(1, "李四");
Person person3 = new Person(1, "李四");
Person person4 = new Person(1, "李四");
Set<Person> set = new HashSet<>();
//在调用add方法的时候 底层在调用hashCode方法和equals
set.add(person1);
set.add(person2);
set.add(person3);
set.add(person4);
System.out.println(set);
//感觉不太合适,发现存的两个对象的内容是一样。真实开发的时候
//只关注内容的,如果内容一样,我也让你存不进去。!!!
//咋办
//总结:以后set集合中如果想存对象的时候,要求对象的内容如果一样的
//话,不能存到set集合中,咋办?重写equals方法和hahsCode方法
//hash值不一样,对象一定不一样。
//对象一样的话,hash只能一定一样
}
}
也是实现了Set集合,可以保证数据 唯一性,存储也是无序的
package com.qfedu.c_treeSet;
import java.util.Set;
import java.util.TreeSet;
public class Demo1 {
public static void main(String[] args) {
//TreeSet在存储的数据的时候 会排序
Set<Integer> set = new TreeSet<>();
set.add(89);
set.add(79);
set.add(69);
set.add(109);
set.add(39);
System.out.println(set);
Set<String> set1 = new TreeSet<>();
set1.add("d");
set1.add("w");
set1.add("a");
set1.add("c");
System.out.println(set1);
}
}
如果想要在TreeSet集合中添加对象的话
要去实现Comparable这个接口
抽象方法:
int
compareTo(T o)
将此对象与指定的对象进行比较以进行排序。
将此对象与指定的对象进行比较以进行排序。 返回一个负整数,零或正整数,因为该对象小于,等于或大于指定对象。
stu1.comparetTo(stu2)
得有一个int类数据
好好思考一个问题:你得给我返回一个int类型的数据
? stu1有age变量 stu1的年龄 减去 stu2的年领
如果年龄返回值是一个负数的话: stu1的年领小与 stu 2
如果年龄返回值是一个0的话,stu1的年龄和stu2年龄相等
如果年龄返回值是一个正整数的话: stu1的年领大于 stu 2
stu1 45
stu2 35
stu3 25
compareTo
set.add(stu1); 第一次调用compareTo
stu1和stu1在比较 45-45 =0 只保留 stu1
set.add(stu2)的时候
又调用compareTo() 第二次调用compareTo
o:stu1
this: stu2 35 - 45 = -10 负数 stu2 比stu1小 咋排 [stu2, stu1]
set.add(stu3)的时候 第三次调用compareTo
this: stu3
o: stu1
[stu3, stu1]
第四次调用compareTo
this:stu3
o:stu2 [stu3 stu2]
[stu3 stu2 stu1]
package com.qfedu.c_treeSet;
import java.util.Set;
import java.util.TreeSet;
class Student implements Comparable<Student>{
String name;
int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Student o) {
System.out.println("123");
int num = this.age - o.age;
return num;
}
}
public class Demo2 {
public static void main(String[] args) {
Student stu1 = new Student("老邢", 45);
Student stu2 = new Student("老邢", 35);
Student stu3 = new Student("saolei", 25);
Student stu4 = new Student("老万", 87);
//按照年龄进行排序 存到TreeSet集合中
Set<Student> set = new TreeSet<>();
set.add(stu1);
set.add(stu2);
set.add(stu3);
set.add(stu4);
System.out.println(set);
// Exception in thread "main" java.lang.ClassCastException:
// com.qfedu.c_treeSet.Student cannot be cast to java.lang.Comparable
// at java.util.TreeMap.compare(TreeMap.java:1294)
//类转换异常的错误,Student转换不了Comparable
//y因为底层在进行排序的时候,实现了Comparable这个接口
//为啥泛型String没有报错 Integer也没有报错
}
}
总结:
1.Object类 都有快捷键
2.HashSet存对象的时候,一定在类中重写equals和hashCode方法
3.TreeSet存对象的时候,一定要实现一个接口Comparable,重写compareTo方法
比较两个对象某个属性的int类型差值
数据结构简单的介绍
通过查阅API我们得知TreeSet集合是基于TreeMap的实现,而TreeMap是基于二叉树(红黑树)结构,也就是说TreeSet集合的底层使用的二叉树(红黑树)结构。
树结构:它也是数据结构中的一种。在计算机领域中树结构指的是倒立的树。
树结构存储的数据,每个数据也需要节点来保存。
而TreeSet集合底层是二叉树的数据结构,什么是二叉树呢?
二叉树:每个节点的下面最多只能有2个子节点。
说明:最多表示一个节点下面可以有两个子节点或者一个子节点或者没有子节点。
在二叉树的根节点左侧的节点称为左子树,在根节点的右侧的节点称为右子树。
既然已经得知TreeSet集合底层是二叉树,那么二叉树是怎样存储数据的呢?是怎样保证存储的数据唯一并有序的呢?
二叉树的存储流程:
当存储一个元素的时候,如果是树的第一个元素,这个元素就作为根节点。
如果不是第一个元素,那么就拿要存储的元素与根节点进行比较大小:
大于根元素:就将要存储的元素放到根节点的右侧,作为右叶子节点。
等于根元素:丢弃。
小于根元素:就将要存储的元素放到根节点的左侧,作为左叶子节点。
总结:二叉树是通过比较大小来保证元素唯一和排序的。
20 10 31 5 13 23 51
类 都有快捷键
2.HashSet存对象的时候,一定在类中重写equals和hashCode方法
3.TreeSet存对象的时候,一定要实现一个接口Comparable,重写compareTo方法
比较两个对象某个属性的int类型差值
数据结构简单的介绍
通过查阅API我们得知TreeSet集合是基于TreeMap的实现,而TreeMap是基于二叉树(红黑树)结构,也就是说TreeSet集合的底层使用的二叉树(红黑树)结构。
树结构:它也是数据结构中的一种。在计算机领域中树结构指的是倒立的树。
树结构存储的数据,每个数据也需要节点来保存。
而TreeSet集合底层是二叉树的数据结构,什么是二叉树呢?
二叉树:每个节点的下面最多只能有2个子节点。
说明:最多表示一个节点下面可以有两个子节点或者一个子节点或者没有子节点。
在二叉树的根节点左侧的节点称为左子树,在根节点的右侧的节点称为右子树。
既然已经得知TreeSet集合底层是二叉树,那么二叉树是怎样存储数据的呢?是怎样保证存储的数据唯一并有序的呢?
二叉树的存储流程:
当存储一个元素的时候,如果是树的第一个元素,这个元素就作为根节点。
如果不是第一个元素,那么就拿要存储的元素与根节点进行比较大小:
大于根元素:就将要存储的元素放到根节点的右侧,作为右叶子节点。
等于根元素:丢弃。
小于根元素:就将要存储的元素放到根节点的左侧,作为左叶子节点。
总结:二叉树是通过比较大小来保证元素唯一和排序的。
20 10 31 5 13 23 51