目录
一. Set接口
-
1. HashSet
-
1.1数据结构:哈希表
-
1.2无序不重复
-
1.3保证元素的唯一性
-
-
2. TreeSet
-
2.1 数据结构:红黑树(特殊的二叉查找树)
-
2.2 TreeSet集合排序的两种方式
-
二. Map接口
-
1. HashTable
-
2. HashMap
-
2.1 使用示例
-
2.2键值对的遍历
-
-
3. TreeMap
三. Java异常处理
-
1.主要内容
-
2. 自定义异常类
==============================================================
正文
一、Set接口
Set继承于Collection接口,是一个不允许出现重复元素,并且无序的集合,使用了默认排序,主要有HashSet和TreeSet两大实现类。
- 注意: 无序指的是:元素的存入和取出的顺序不一定一致
- 在判断重复元素的时候,Set集合会调用hashCode()和equal()方法来实现。
- 它没有提供额外的方法,可以说Set就是一个Collection
set集合添加元素并使用迭代器迭代元素:
public class MyClass {
public static void main(String[] args) throws IOException {
//Set 集合存和取的顺序不一致
Set set = new HashSet();
set.add("唐僧");
set.add("孙悟空");
set.add("猪八戒");
set.add("沙和尚");
System.out.println(set);
//[沙和尚, 孙悟空, 猪八戒, 唐僧]
Iterator iterator = set.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
Set集合框架图:Set常见方法 :
编号 | 方法 | 描述 |
---|---|---|
1 | add() | 添加一个对象到集合中。 |
2 | clear() | 从集合中删除所有对象。 |
3 | contains() | 如果指定的对象是集合中的元素,则返回true。 |
4 | isEmpty() | 如果集合没有元素,则返回true。 |
5 | iterator() | 返回集合的Iterator对象,该对象可用于检索对象。 |
6 | remove() | 从集合中删除指定对象。 |
7 | size() | 返回集合中的元素数。 |
1. HashSet
- LinkedHashSet会保存插入的顺序。
1.1数据结构:哈希表
Hash是一种数据结构,用户查找对象。Hash为每一个对象计算出一个整数,称为Hash Code(哈希值)。哈希表是按照哈希值来存的。当我们添加元素时,哈希值是一样的,这时候,会进行是否是同一对象判断equals,如果不是同一对象,那么会在当前对象下顺延(串下来的)。
HashSet对于判断元素是否存在以及删除等操作依赖的方法是元素的hashcode和equals方法
查看哈希值:
Person xw = new Person();
System.out.println(xw);
//swu.gyl.javatest.Person@75b84c92
//Object 类的 toString 方法返回一个字符串
//getClass().getName() + '@' + Integer.toHexString(hashCode())
//75b84c92就是哈希值
1.2无序不重复
public static void main(String[] args) {
HashSet<String> hs = new HashSet<String>();
System.out.println(hs.add("java1"));
System.out.println(hs.add("java1"));
hs.add("java2");
Iterator<String> it = hs.iterator();
while(it.hasNext()){
System.out.println(hs.add(it.next()));
}
}
//哈希值一样,同一对象。添加失败。存入和取出顺序不一致。
输出:1.3保证元素的唯一性
( 1 ) 如果元素的hashCode值不同,不会调用equals,添加成功
( 2 ) 如果元素的hashCode值相同,才会判断equals是否为true,为true添加失败
举一个栗子:hashSet存自定义对象Person,当姓名和年龄一致,元素重复。
所以,当我们自定义对象的时候,一般要复写hashcode和equals方法,因为自定义对象可能要存放到hashSet集合中。还有,复写hashCode要尽量保证哈希值的唯一性,一般根据判断条件生成。
public static void main(String[] args) {
HashSet<Person> hs = new HashSet<Person>();
hs.add(new Person("a1", 11));
hs.add(new Person("a2", 22));
hs.add(new Person("a3", 33));
hs.add(new Person("a3", 33));
Iterator<Person> it = hs.iterator();
while(it.hasNext()){
Personperson = (Person)it.next();
sop(person.getName()+"::"+person.getAge());
}
//重写了equals,没重写hashcode方法。发现equals发现没被调用,而且都存入成功。说明计算得到是不同的哈希值。
// 鉴于需求,我们需要去重写。说明,我们需要覆盖hashcode方法,建立自己的哈希值。
// 哈希值的生成根据判断条件
// 重写hashcode方法,发现,去重成功了。而且equals方法运行了。
}
class Person{
private String name;
private int age;
public Person(String n,int a){
this.name = n;
this.age = a;
}
public String getName(){
return this.name;
}
public int getAge(){
return this.age;
}
public boolean equals(Object obj){
if(!(obj instanceof Person))
return false;
Personp = (Person)obj;
System.out.println(this.name+"...."+this.age);
return this.name.equals(p.getName()) && this.age == p.getAge();
}
public int hashCode()
{
System.out.println(this.name+"...hashcode");
//return 60; 会有很多重复比较
return this.name.hashCode()+this.age*13;
}
2. TreeSet
红-黑树的数据结构,默认对元素进行自然排序,如果在比较的时候两个对象返回值为0,那么元素重复
2.1 数据结构:红黑树(特殊的二叉查找树)
红黑树算法的规则: 左小右大。
2.2 TreeSet集合排序的两种方式:
- 方式一: 让元素自身具备比较性,实现Comparetor<t>接口,并重写compare方法;
// 可以排序的集合
TreeSet<People> score = new TreeSet<>(new Comparator<People>() {
@Override
public int compare(People people, People t1) {
return people.compareTo(t1);
}
});
class People implements Comparable{
String name;
int age;
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public People(String name, int age){
this.name = name;
this.age = age;
}
- 方式二:让容器自身具备比较性,自定义比较器,实现Comparable接口,覆盖compareTo 方法。
TreeSet<People> score = new TreeSet<>((People p1,People p2) -> p1.compareTo(p2));
People p1 = new People("jack",20);
People p2 = new People("marry",30);
People p3 = new People("Tom",25);
score.add(p1);
score.add(p2);
score.add(p3);
if (p1.hashCode() == p2.hashCode()){
System.out.println("相同");
}else{
System.out.println("不相同");
}
System.out.println(score);
//equals 比较对象内部的内容
// 使用的两个对象必须实现 Comparable接口的compareTo方法
//在compareTo里面实现具体该如何比较
@Override
public int compareTo(Object o) {
// 1.判断o对象是不是People的一个对象
if (o instanceof People){
People o1 = (People)o;
//自己规定比较的策略
if (this.age != o1.age){
return this.age - o1.age;
}else {
//年龄相同的情况下 再比姓名的字母
return this.name.compareTo(o1.name);
}
}else {
return 0;
}
}
}
二、Map接口
Map是一种依照键(key)存储元素的容器,键(key)很像下标,在List中下标是整数。在Map中键(key)可以使任意类型的对象。Map中不能有重复的键(Key),每个键(key)都有一个对应的值(value)。
一个键(key)和它对应的值构成map集合中的一个元素。
Map中的元素是两个对象,一个对象作为键,一个对象作为值。键不可以重复,但是值可以重复。
将键映射到值的对象,一个映射不能包含重复的键;每个键最多只能映射到一个值。
[图片上传中...(image.png-7df4a3-1566048732614-0)]
Map 接口常用方法:
序号 | 方法 | 描述 |
---|---|---|
1 | void clear() | 从此映射中移除所有映射关系。 |
2 | boolean containsKey(Object k) | 如果此映射包含指定键的映射关系,则返回 true。 |
3 | boolean containsValue(Object v) | 如果此映射将一个或多个键映射到指定值,则返回 true。 |
4 | Set entrySet( ) | 返回此映射中包含的映射关系的 Set 视图。 |
5 | boolean equals(Object obj) | 比较指定的对象与此映射是否相等。 |
6 | Object get(Object k) | 返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。 |
7 | nt hashCode( ) | 返回此映射的哈希码值。 |
8 | boolean isEmpty( ) | 如果此映射未包含键-值映射关系,则返回 true。 |
9 | Set keySet( ) | 返回此映射中包含的键的 Set 视图。 |
10 | Object put(Object k, Object v) | 将指定的值与此映射中的指定键关联。 |
11 | void putAll(Map m) | 从指定映射中将所有映射关系复制到此映射中。 |
12 | Object remove(Object k) | 如果存在一个键的映射关系,则将其从此映射中移除。 |
13 | int size( ) | 返回此映射中的键-值映射关系数。 |
14 | Collection values( ) | 返回此映射中包含的值的 Collection 视图。 |
1. HashTable
底层是哈希表数据结构,线程是同步的,不可以存入null键,null值。
效率较低,被HashMap 替代。
2. HashMap
底层是哈希表数据结构,线程是不同步的,可以存入null键,null值。要保证键的唯一性,需要覆盖hashCode方法,和equals方法。
它的子类LinkedHashMap,是双向链表来维护key-value对的次序,该链表定义了迭代顺序,该迭代顺序与key-value对的插入顺序保持一致。
2.1 使用示例:
//HashMap 集合 存储数据的特点 键key-值value
//key不能重复 可以是任意的对象类型 通常使用字符串String
HashMap<String,Integer> score = new HashMap<>();
//添加对象 键值对
score.put("Chinese",89);
score.put("Math",95);
score.put("English",99);
//更改某个键对应的值
score.put("Chinese",91);
//获取键值对的个数
score.size();
//获取所有的key
System.out.println(score.keySet());
//获取所有的值
System.out.println(score.values());
//获取Entry:key-value
System.out.println(score.entrySet());
//获取一个key对应的值
System.out.println(score.get("English"));
2.2键值对的遍历
- 方式一:通过遍历key来得到每一个 key对应的值
for (String key:score.keySet()){
//通过key得到值value
int s = score.get(key);
System.out.println("key: "+key+" value: "+s);
}
- 方式二:通过EntrySet 得到Entry对象的集合
//一个Entry管理一个键值对 getKey getValue
Set<Map.Entry<String,Integer>> entries = score.entrySet();
for (Map.Entry entry:entries){
//得到Entry对应的key
String key = (String)entry.getKey();
//获取Entry对应的值
Integer value = (Integer) entry.getValue();
System.out.println("key: "+key+" value: "+value);
}
- 方式三:通过values 获取所有值,不能获取到key对象
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "aaaa");
map.put(2, "bbbb");
map.put(3, "cccc");
System.out.println(map);
// 通过values 获取所有值,不能获取到key对象
// Collection<V> values()
Collection<String> vs = map.values();
Iterator<String> it = vs.iterator();
while (it.hasNext()) {
String value = it.next();
System.out.println(" value=" + value);
}
3. TreeMap
底层是哈希表数据结构,线程是不同步的,可以存入null键,null值。要保证键的唯一性,需要覆盖hashCode方法,和equals方法。
//主要实现
Set<Entry<Person, String>> entrySet = hm.entrySet();
Iterator<Entry<Person, String>> it = entrySet.iterator();
while (it.hasNext()) {
Entry<Person, String> next = it.next();
Person key = next.getKey();
String value = next.getValue();
System.out.println(key + " = " + value);
}
@Override
public int hashCode() {
return this.name.hashCode() + age * 37;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Person) {
Person p = (Person) obj;
return this.name.equals(p.name) && this.age == p.age;
} else {
return false;
}
}
@Override
public String toString() {
return "Person@name:" + this.name + " age:" + this.age;
}
三、异常处理(点击了解更多)
异常处理 ,处理运行过程中出现的不可控的错误,使程序更健壮。
1.主要内容
- 如果需要自己处理异常 就catch
- 如果有多个异常 可以使用多个catch来捕获, catch 的顺序从小到大
- 如果异常出现 后面的代码将不会执行
- finally关键字用来创建在 try 代码块后面执行的代码块。无论是否发生异常,finally 代码块中的代码总会被执行。在 finally 代码块中,可以运行清理类型等收尾善后性质的语句。
- 使用throws抛出异常 交给外部处理
public static void test() throws FileNotFoundException,NullPointerException{
FileReader fr = new FileReader("");
}
- 使⽤throw抛出⼀个⾃⼰创建的异常对象
public static void test2() throws IllegalAccessException {
//自己抛出异常
if (1 > 2){
throw new IllegalAccessException();
}
}
2. 自定义异常类:能够⾃⼰定义输出内容 更快地找到出现问题的位置
public static void test3() throws GYLException {
//....
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
StackTraceElement e = stackTrace[2];
String detail = e.getFileName()+"->"+e.getMethodName()+"->"+e.getLineNumber();
throw new GYLException("自己的异常类:无所作为"+detail);
}
//自定义异常
class GYLException extends Exception{
//1.提供一个无参构造方法
public GYLException(){
}
//2.提供一个有参构造方法 参数是一个字符串
public GYLException(String desc){
super(desc);
}
}
//捕获自己的异常
try {
TException.test3();
} catch (GYLException e) {
e.printStackTrace();
}
// 输出结果:
// GYLException: 自己的异常类:无所作为Exception1.java->main->74
四、心得体会
今天学到了很多新知识点,要花更多的时间来消化,加油!!!