java学习笔记017

一.Set 接口

1.基本概念

Set : 是 Collection 的子接口, 特点是无序不可重复(自动去重),

新增方法: Set< E > of(E... elements)返回包含任意数量元素的不可修改集合。 无序: 存放的顺序与内部真实存储的顺序不一致(内部有自己存储的规则). 去重: 两个数据调用equals方法返回值true,相同需要去重,false不同可以添加.

遍历方式只有两种 :1.for each 2.迭代器 iterator

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
​
public class Set {
    public static void main(String[] args) {
        Set<Integer> set = new HashSet<>();
        set.add(123);//自动去重只能存进去一个
        set.add(123);
        System.out.println(set);//[123]
​
        Set<String> set2 = new HashSet<>();
        set2.add("哈哈");
        set2.add("ab");
        set2.add("呵呵");
        set2.add("bd");
        set2.add("a");
        set2.add("吼吼");
        System.out.println(set2);//[ab, a, bd, 哈哈, 呵呵, 吼吼]真实的存储顺序与实际存入顺序不同, 按照集合内部自己的排序方式.
        //for each遍历
        int i= 1;
        for (Object obj:set2) {
            if(i==set2.size()){
                System.out.print(obj);
                break;
            }
            System.out.print(obj+"   ");
            i++;
        }
        //迭代器遍历
        Iterator it = set2.iterator();
        while (it.hasNext()){
            System.out.print(it.next()+"   ");
        }
​
        //static <E> Set<E> of(E... elements) 返回包含任意数量元素的不可修改集。
        Set<Integer> set3 = Set.of(1,2,3,4,5);
    }
}

2.HashSet实现类

HashSet : Set 接口的实现类.无新增功能,无序不可重复. 底层结构: 哈希表 (数组+链表+红黑树) ->是由HashMap维护. 优点 : 查询,增删效率较高. 应用场景: 实现不存储相同数据,查询,增删效率较高的时候建议使用HashSet

哈希表 : 数组+链表+红黑树

存储数据的步骤:

  1. 数据首先传给 hashcode ( ) 方法, hashcode 方法默认根据对象的地址通过hash指定的算法计算后返回一个int类型的整数.

  2. 得到返回的int整数后,通过指定的hash算法计算数据要存在数组的哪个索引位置,不同的jdk版本哈希算法不尽相同,一般会尽量分散在数组的每个索引位置.

  3. 确定索引位置后,如果在指定的索引位置中没有链表及节点存在,直接把这个数据作为链表头存入这个索引位置, 如果已经有链表存在, 就需要遍历这个链表的每一个节点,调用 equals 方法比较这个数据与链表中的节点数据是否相等,如果每一个都不相等就把这个数据存入这个链表的最后.

  4. 当链表长度>8并且数组的总长度>64的时候,会把链表变为红黑树.

注意: 前提是重写hashcode与equals方法,让它根据成员变量值去计算而不是对象地址.equals相等,hashcode的结果一定相等; hashcode结果一样, equals 不一定相等.

import java.util.HashSet;
import java.util.Objects;
​
public class HashSet {
    public static void main(String[] args) {
        HashSet<Person> hash = new HashSet();
        hash.add(new Person("天一","男",18));
        hash.add(new Person("天二","男",23));
        hash.add(new Person("天三","男",19));
        hash.add(new Person("天四","男",24));
        hash.add(new Person("天五","男",25));
        hash.add(new Person("天五","男",25));
        //两个天五只能存进去一个
        for (Person p:hash) {
            System.out.println(p);
        }
    }
}
//自定义类引用数据类型
class Person{
    private String name;
    private String gender;
    private int age ;
​
    public Person() {
    }
​
    public Person(String name, String gender, int age) {
        this.name = name;
        this.gender = gender;
        this.age = age;
    }
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public String getGender() {
        return gender;
    }
​
    public void setGender(String gender) {
        this.gender = gender;
    }
​
    public int getAge() {
        return age;
    }
​
    public void setAge(int age) {
        this.age = age;
    }
​
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                ", age=" + age +
                '}';
    }
​
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age &&
                Objects.equals(name, person.name) &&
                Objects.equals(gender, person.gender);
    }
​
    @Override
    public int hashCode() {
        return Objects.hash(name, gender, age);
    }
}

3. TreeSet 实现类

TreeSet : Set接口的实现类,无序不可重复.

3.1基本定义

底层结构: 红黑树(平衡二叉树). 特点: 自动做生序排序. 新增功能: 新增了一些能够比较的相关功能.

public class TreeSet {
    public static void main(String[] args) {
        TreeSet<Integer> set = new TreeSet<>();
        set.add(5);
        set.add(2);
        set.add(1);
        set.add(3);
        set.add(4);
        System.out.println(set);[1,2,3,4,5]
​
        //E ceiling(E e) 返回此set中大于或等于给定元素的 null元素,如果没有这样的元素,则 null 。
        System.out.println(set.ceiling(6));//没有大于6的,null
​
        //E first() 返回此集合中当前的第一个(最低)元素。
        System.out.println(set.first());
        //E last() 返回此集合中当前的最后一个(最高)元素。
        System.out.println(set.last());
​
        //E higher(E e) 返回此集合中的最小元素严格大于给定元素,如果没有这样的元素,则 null 。
        System.out.println(set.higher(1));//从第一个开始比较拿出第一个比1大的值.
​
        //E pollFirst() 检索并删除第一个(最低)元素,如果此组为空,则返回 null 。
        //E pollLast() 检索并删除最后一个(最高)元素,如果此集合为空,则返回 null 。
        System.out.println(set.pollFirst());//删除第一个数
        System.out.println(set.pollLast);//删除最后一个数
    }
}

3.2 比较器(比较规则)

在 TreeSet 存储自定义引用数据类型的数据时, 存储对象的排序与去重都需要指定比较规则.

按编写位置分为:内部比较器和外部比较器.在没有指明使用外部比较器(定制排序)的情况下,默认使用内部比较器(自然排序).

  1. 内部比较器 | 自然排序 :定义在需要存储的引用数据类型的类内部的一个指定的比较方式(方法).缺点是代码固定不够灵活.

    步骤:1)让引用数据类型的类实现 Comparable 接口, 2)重写 Comparable 的 compareTo ( T o )方法,返回值为 int 类型. T1.compare( T2 ) .比较两个数据的大小, 当返回值为 0 时->T1 = T2 , 返回正数时-> T1 > T2 .返回负数时-> T1 < T2 .

  1. 外部比较器 | 定制排序 : 定义在要存储的引用数据类型的类外部的一个指定的比较规则(方法).

    步骤:1)让引用数据类型的类实现 Comparator 接口, 重写 compare ( T t1, T t2)方法返回值为 int 类型. t1.compare( t2 ) .比较两个数据的大小, 当返回值为 0 时->t1 = t2 , 返回正数时-> t1 > t2 .返回负数时-> t1 < t2 .

import java.util.Arrays;
import java.util.Comparator;
​
public class TreeSet {
    public static void main(String[] args) {
        //指明外部比较器
        //com 可简化为lambda表达式 (x,y)->x.getAge()-y.getAge()
        TreeSet<User> treeSet = new TreeSet<>(com);
        treeSet.add(new User("孙悟空","男",9999));
        treeSet.add(new User("盖伦","男",30));
        treeSet.add(new User("彦","女",6500));
        treeSet.add(new User("赵信","男",32));
        treeSet.add(new User("炙心","女",4300));
        treeSet.add(new User("卡尔","男",9999));
        //匿名内部类
        Comparator<User> com = new Comparator<User>() {
            @Override
            public int compare(User o1, User o2) {
                if(o1.getGender().compareTo(o2.getGender())==0){
                    return o1.getAge()-o2.getAge();
                }
                return o1.getGender().compareTo(o2.getGender());
            }
        };
         
        for (User u:users) {
            System.out.println(u);
        }
    }
}
//数据类型的类实现Comparable接口,<User>表示只能比较这个类型的对象数据
public class User implements Comparable<User>{
​
        private String name;
        private String gender;
        private int age ;
​
        public User() {
        }
​
        public User(String name, String gender, int age) {
            this.name = name;
            this.gender = gender;
            this.age = age;
        }
​
        public String getName() {
            return name;
        }
​
        public void setName(String name) {
            this.name = name;
        }
​
        public String getGender() {
            return gender;
        }
​
        public void setGender(String gender) {
            this.gender = gender;
        }
​
        public int getAge() {
            return age;
        }
​
        public void setAge(int age) {
            this.age = age;
        }
​
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", gender='" + gender + '\'' +
                    ", age=" + age +
                    '}';
        }
​
​
         @Override
         public boolean equals(Object o) {
             if (this == o) return true;
             if (o == null || getClass() != o.getClass()) return false;
             User user = (User) o;
             return age == user.age &&
                     Objects.equals(name, user.name) &&
                     Objects.equals(gender, user.gender);
         }
​
         @Override
         public int hashCode() {
             return Objects.hash(name, gender, age);
         }
        //重写compareTo(T o)方法.内部比较器
        @Override
        public int compareTo(User o) {
            if(this.getName().compareTo(o.getName())==0){
                if(this.getAge()-o.getAge()==0){
                    this.getGender().compareTo(o.getGender());
                }else {
                    return this.getAge()-o.getAge();
                }
            }
            return this.getName().compareTo(o.getName());
        }
}

二.Map<K,V>接口

1.基本定义

Map<K,V> : 集合中的元素由键值对k-v组成, Map的无序与去重 由key决定 k: 可以为任意引用数据类型数据 --> Set 无序不可重复 v: 可以为任意引用数据类型数据 --> Collection 可重复无序 一个key只能对应一个value->映射关系, 可以根据key操作value

import java.util.HashMap;
import java.util.Map;
public class Map {
    public static void main(String[] args) {
        //创建Map集合,key存储int类型数据,value储存String类型数据
        Map<Integer,String> map = new HashMap<>();
        //V put(K key, V value) 将指定的值与此映射中的指定键相关联。
        map.put(1001,"张三");//成对储存
        map.put(1002,"李四");
        map.put(1003,"王五");
​
        System.out.println(map.put(1002,"LISA"));//重复的key,value值会被覆盖,返回被覆盖的值
        System.out.println(map);
        //V get(Object key) 返回指定键映射到的值,如果此映射不包含键的映射,则返回 null 。
        System.out.println(map.get(1001));
​
        //boolean containsKey(Object key) 如果此映射包含指定键的映射,则返回 true 。
        //boolean containsValue(Object value) 如果此映射将一个或多个键映射到指定值,则返回 true 。
        System.out.println(map.containsKey(1003));
        System.out.println(map.containsValue("zhangsan"));
​
        //V remove(Object key) 如果存在,则从该映射中移除键的映射。
        System.out.println(map.remove(1001));
        System.out.println(map);
    }
}

2.遍历方式

1.keySet 获取所有的key值,返回一个set集合.既可以获取到key,也可以获取到value. 2.values() 获取map集合中所有键值对的value,返回一个Collection集合.只能获取到value, 3.entrySet() 获取所有的键值对->Map.Entry 类型->表示一个键值对.

import java.util.*;
​
public class Each {
    public static void main(String[] args) {
        //创建Map集合
        Map<Integer,String> map = new HashMap<>();
        map.put(1000,"天");
        map.put(1001,"地");
        map.put(1002,"人");
​
        //1.keySet
        Set<Integer> keys = map.keySet();
        for (Integer i :keys){
            System.out.println(i+"<-->"+map.get(i));
        }
        //2.values
        Collection<String> val = map.values();
        for(String s:val){
            System.out.println(s);
        }
        //3.entrySet
        Set<Map.Entry<Integer,String>> set = map.entrySet();
        Iterator<Map.Entry<Integer,String>> it = set.iterator();
        for(;it.hasNext();){
            Map.Entry entry = it.next();
            System.out.println(entry.getKey()+"<-->"+entry.getValue());
        }
    }
}

3.HashMap实现类

底层结构: 哈希表(数组+链表+红黑树).特点: 查询,增删效率较高.

扩容问题: 初始容量16,newCap = oldCap << 1 数组每次扩容原容量的两倍 DEFAULT_INITIAL_CAPACITY 初始容量 16 DEFAULT_LOAD_FACTOR : 默认加载因子 0.75 threshold : 扩容临界值 DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY

在使用HashMap存储自定义的引用数类型的数据时, 类型中应该重写hashcode方法(作为比较规则)实现去重和value的覆盖.

import java.util.Set;
import java.util.TreeMap;
​
public class HashMap {
    public static void main(String[] args) {
        HashMap<Teachers,String> hmap = new HashMap<>();
​
        hmap.put(new Teachers("殷老师","java初级"),"5年");//被覆盖
        hmap.put(new Teachers("李老师","大数据"),"6年");
        hmap.put(new Teachers("裴老师","java高级"),"7年");
        hmap.put(new Teachers("廖老师","java中级"),"8年");
        hmap.put(new Teachers("卢老师","java鼓励师"),"9年");
        hmap.put(new Teachers("殷老师","董事长"),"2年");
        Set<Teachers> set = hmap.keySet();
        for(Teachers s:set){
            System.out.println(s+"<-->"+hmap.get(s));
        }
    }
}

4.TreeMap实现类

TreeSet底层是由TreeMap维护的,TreeMap 新增了一些有关于比较的方法. 底层结构: 红黑树. 特点: 自动做升序排序(根据key做升序)(key为自定义引用数据类型时需要比较器).

import java.util.Set;
import java.util.TreeMap;
​
public class TreeMap {
    public static void main(String[] args) {
        TreeMap<Teachers,String> tmap = new TreeMap<>((t1,t2)->t1.getName().compareTo(t2.getName()));
​
        tmap.put(new Teachers("殷老师","java初级"),"5年");
        tmap.put(new Teachers("李老师","大数据"),"6年");
        tmap.put(new Teachers("裴老师","java高级"),"7年");
        tmap.put(new Teachers("廖老师","java中级"),"8年");
        tmap.put(new Teachers("卢老师","java鼓励师"),"9年");
        tmap.put(new Teachers("殷老师","董事长"),"2年");
        Set<Teachers> set = tmap.keySet();
        for(Teachers s:set){
            System.out.println(s+"<-->"+tmap.get(s));
        }
    }
}

5.Properties 类

Properties : 存储字符串类型的键值对,特点是可以保存到流中或从流中加载。

优点 : 可以通过Properties实现软编码,从满足Properties特点的配置文件中读取数据,便于后期维护.

使用步骤: 1.定义一个(后缀名为.properties的)配置文件 xx.properties (键值对都是字符串), 在文件中保存键值对.(如: 张三=河南人) 2.创建Properties类型的对象,调用load从流中加载(输入流的数据源就是配置文件). 3.从配置文件中读取数据,加载使用.

import java.io.IOException;
import java.util.Properties;
public class Properties {
    public static void main(String[] args) throws IOException {
        Properties pro = new Properties();
​
        //void load(InputStream inStream) 从输入字节流中读取属性列表(键和元素对)。
        pro.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));
        System.out.println(pro.getProperty("username"));//zhangsan
        System.out.println(pro.getProperty("password"));//root
    }
}
db.properties : 配置文件
    username=zhangsan
    password=root
上一篇:究竟什么病毒轻而易举感染了全球8500万部手机?


下一篇:详解全站 HTTPS 访问优化