Set ,HashSet ,哈希表(数组+链表+红黑树),TreeSet ,Map,HashMap,TreeMap,Properties ,Collections, 如何处理HashMap的线程不安全

Set : 无序的  不可重复
*  新增功能: static <E> Set<E> of(E... elements) 返回包含任意数量元素的不可修改集。
*           其他方法从Collection继承
*  遍历方式:
*      foreach
*      iterator
*
*  注意:
*      存放数据的顺序与内部真实存储的顺序可能不一致

public class Class001_Set {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        //去重  无序
        set.add("bcd");
        set.add("abc");
        set.add("abc");
        set.add("bc");
        set.add("ab");

        System.out.println(set);

        //遍历方式
        //foreach
        for(String str:set){
            System.out.println(str);
        }

        //iterator
        Iterator<String> it =  set.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }

        //新增
        Set<Integer> set2 = Set.of(3,1,2,5,4);
        System.out.println(set2);
        //不可变
        //set2.remove(3);

        System.out.println(set2);
    }
}

HashSet  --> 是由HashMap维护的
    无序的,不可重复

    底层结构: 哈希表(数组+链表+红黑树)
    特点: 查询,增删效率较高
          无序,去重
    应用场景 : 存储数据由单个值决定的情况下,想要去重的情况下,适合使用HashSet
    新增内容 : 无新增方法

 

 

 哈希表中hashcode与equals之间的关系(前提是重写hashcode与equals都是根据成员变量计算)
    equals相等hashcode一定相等
    hashcode相等,equals不一定相等

哈希表存储自定义引用数据类型数据的去重:
 需要在数据的类型中重写hashcode与equals方法,实现根据内容(成员变量的值)进行比较和计算

练习: 定义一个HashSet集合,存储自定义引用数据类型数据,是否对象根据成员内容去重

public class Class002_HashSet {
    public static void main(String[] args) {
        HashSet<Person> set = new HashSet<>();

        set.add(new Person("小红",18));
        set.add(new Person("小明",19));
        set.add(new Person("小红",18));
        set.add(new Person("小小彬",17));

        System.out.println(set);

        System.out.println(new Person("小红",18).hashCode());
        System.out.println(new Person("小红",18).hashCode());

    }
}

class Person{
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    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;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", 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);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

TreeSet --> 是由TreeMap维护的
 无序,去重
 底层结构 : 红黑树(平衡二叉树)
 特点 : 默认升序排序
 新增方法 : 数据的大小比较相关的方法,因为红黑树结构中数据已经比较过大小,默认升序

public class Class003_TreeSet {
    public static void main(String[] args) {
        TreeSet<Double> tree = new TreeSet<>();

        tree.add(3.3);
        tree.add(1.1);
        tree.add(2.2);
        tree.add(4.4);
        tree.add(5.5);
        tree.add(5.5);

        System.out.println(tree);

        //测试新增 方法
        System.out.println(tree.first());
        System.out.println(tree.last());
        System.out.println(tree.ceiling(2.1));
        System.out.println(tree.floor(3.3));

        TreeSet<String> tree2 = new TreeSet<>();

        tree2.add("abc");
        tree2.add("bc");
        tree2.add("ab");
        tree2.add("a");
        tree2.add("b");
        tree2.add("ab");

        System.out.println(tree2);
    }
}

 思考: TreeSet集合中能够成功存储不同类型的数据?
         使用TreeSet存储自定义的引用数据类型,如何是否去重(根据内容去重),实现默认升序排序?

    ClassCastException : 类型转换异常
    问题: 在存储自定义引用数据类型数据的时候,对象数据不确定比较规则,在TreeSet无法实现比较,无法排序
    需要: 指定学生数据的比较规则
            内部比较规则|内部比较器|自然排序
                实现一个java.lang.Comparable接口,重写compareTo方法,在compareTo方法内部指定比较规则
                定义在类的内部,是一种默认的比较规则
            外部比较规则|外部比较器|定制排序

    实现内部比较器: 定义一个TreeSet集合存储学生信息,要求根据学生姓名进行排序,实现根据姓名降序排序
 */
public class Class004_TreeSet {
    public static void main(String[] args) {
        TreeSet<Student> tree = new TreeSet<>();

        tree.add(new Student(103,"zhangsan",19));
        tree.add(new Student(102,"lisi",17));
        tree.add(new Student(101,"zhangsan",18));
        tree.add(new Student(101,"wangwu",16));

        System.out.println(new Student(102,"lisi",17).compareTo(new Student(103,"zhangsan",19)));

        System.out.println(tree);


    }
}

  学生类,实现类内部比较规则
 
public class Student implements Comparable<Student>{
    private int id;
    private String name;
    private int age;

    public Student() {
    }

    public Student(int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    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;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    /*
        指定比较规则
            s1.compareTo(s2)-->返回值
                =0       s1=s2
                <0       s1<s2
                >0       s1>s2
     */
    @Override
    public int compareTo(Student o) {
        return o.id-this.id;
    }
}

Map <K,V>
  存储键值对数据
  元素的集合,键值对的集合
  K-V 键值对
  key,value可以为任意引用数据类型的数据
  key--> 唯一的,无序的 --> Set集合
  value --> 无序的,可重复的  -->Collection

  键值对为一个映射关系
  key--> 映射-->value
  一个key只能对应一个value
  一个key可以实现对应一个集合作为value,集合中可以存放多个值

public class Class001_Map {
    public static void main(String[] args) {
        Map<Integer,String> map = new HashMap<>();

        //常用方法
        //V put(K key, V value)  返回被覆盖的value,如果没有覆盖返回null
        System.out.println(map.put(103,"胡歌"));
        System.out.println(map.put(104,"胡歌"));
        System.out.println(map.put(102,"彭于晏"));
        System.out.println(map);
        System.out.println(map.put(104,"胡一菲"));
        System.out.println(map);

        /*
        boolean containsKey(Object key) 如果此映射包含指定键的映射,则返回 true 。
        boolean containsValue(Object value) 如果此映射将一个或多个键映射到指定值,则返回 true 。
         */
        System.out.println(map.containsKey(104));
        System.out.println(map.containsValue("胡歌"));

        //V get(Object key) 返回指定键映射到的值,如果此映射不包含键的映射,则返回 null 。
        System.out.println(map.get(102));

        //static <K,V> Map<K,V> of(K k1, V v1) 返回包含单个映射的不可修改的映射。
        Map<String,Integer> map2 = Map.of("zhangsan",18,"lisi",19);
        System.out.println(map2);

        //V remove(Object key) 如果存在,则从该映射中移除键的映射(可选操作)。
        System.out.println(map.remove(101));
        System.out.println(map);

        //default V replace(K key, V value) 仅当指定键当前映射到某个值时,才替换该条目的条目。
        map.replace(103,"胡哥哥");
        System.out.println(map);
    }
}

 Map集合的遍历方式:
        1.keySet() 获取集合中所有的key,然后遍历key,根据key获取value
        2.values() 获取集合中所有的value
        3.entrySet() 返回多个Map.Entry类型的键值对对象,一个set集合
 */
public class Class002_Map {
    public static void main(String[] args) {
        Map<Integer,String> map = new HashMap<>();

        map.put(103,"胡歌");
        map.put(104,"胡歌");
        map.put(102,"彭于晏");
        map.put(105,"胡一菲");

        //1.keySet
        Set<Integer> keys =  map.keySet();
        for(Integer i : keys){
            System.out.println(i+"-->"+map.get(i));
        }

        //2.values()
        Collection<String> values =  map.values();
        Iterator<String> it = values.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }

        //3.entrySet()
        Set<Map.Entry<Integer,String>> set = map.entrySet();
        for(Map.Entry entry:set){
            System.out.println(entry.getKey()+"-->"+entry.getValue());
        }
    }
}

HashMap
    底层: 哈希表(数组+链表+红黑树)
    特点: 查询,增删效率较高
    新增方法: 无新增方法
    遍历方式: 与map相同
    并允许null值和null键

DEFAULT_LOAD_FACTOR : 默认的加载因子     0.75
DEFAULT_INITIAL_CAPACITY : 默认初始容量  1<<4 = 16
threshold 扩容临界值 | 阀值  CAPACITY*LOAD_FACTOR

扩容: newCap = oldCap << 1 每次扩容原数组容量的2倍

 练习: 定义一个HashMap结构,用来存储指定类型的数据,要求存储key为Teacher,value为Teacher所教授的学科

    去重: key中存储数据的类型要求重写hashcode与equals方法
 */


public class Class003_HashMap {
    public static void main(String[] args) {
        //构建一个HashMap
        HashMap<Teacher,String> map = new HashMap<>();

        map.put(new Teacher("laopei",false,"java"),"java");
        map.put(new Teacher("李毅大帝",false,"db"),"db");
        map.put(new Teacher("曹老师",false,"web"),"web");
        map.put(new Teacher("曹老师",false,"web"),"前端");

        System.out.println(map);

    }
}

 

TreeMap
    根据key实现去重
    底层结构: 红黑树
    特点: 根据key对数据做升序排序
    新增功能: 比较相关的一些方法

    根据key做去重,根据key做排序
    要求: key指定比较规则|方式|比较器|排序
        内部比较器
        外部比较器

定义TreeMap存储键值对数据,key为Teacher
 */
public class Class004_TreeMap {
    public static void main(String[] args) {
        //根据key默认比较规则,对数据进行升序排序
        //TreeMap<Teacher,String> tree = new TreeMap<>();
        //根据实参传递的外部比较规则,对key数据进行升序排序
        TreeMap<Teacher,String> tree = new TreeMap<>((t1,t2)->t1.getSubject().compareTo(t2.getSubject()));

        tree.put(new Teacher("laopei",false,"java"),"java");
        tree.put(new Teacher("李毅大帝",false,"db"),"db");
        tree.put(new Teacher("曹老师",true,"web"),"web");
        tree.put(new Teacher("曹老师",false,"web"),"前端");

        System.out.println(tree);
        System.out.println(tree.firstKey());
        System.out.println(tree.firstEntry()+"-->"+tree.firstEntry().getKey());

    }
}

 Properties :
        存储的键值对都是字符串
         Properties可以保存到流中或从流中加载

         软编码 : 经常改动的内容不要定义在源代码中,定义在一个外部的文件中-->配置文件,从程序中每次动态从文件中进行读取内容,使用读入的最新内容

    配置文件 : properties格式,符合Properties特点: 键值对  都是字符串
 */
public class Class005_Properties {
    public static void main(String[] args) throws IOException {
        Properties pro = new Properties();
        //设置键值对为字符串数据
       /* pro.setProperty("name","张三");
        pro.setProperty("pwd","123");*/

        //获取键值对为字符串的数据
        System.out.println(pro.getProperty("name"));

        System.out.println(pro);

        //void load(InputStream inStream) 从输入字节流中读取属性列表(键和元素对)。
        pro.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));

        //从配置文件中读取数据
        System.out.println(pro.getProperty("name"));
        System.out.println(pro.getProperty("pwd"));
    }
}

 类 java.util.Collections 提供了对Set、List、Map操作的工具方法。

    如何处理HashMap的线程不安全问题:
        1.可以Hashtable
            1).线程安全问题
            2).HashMap允许key与value为null,Hashtable不允许
            3).细节问题,底层源码

        2.static <K,V>Map<K,V> synchronizedMap(Map<K,V> m) 返回由指定映射支持的同步(线程安全)映射。
        3.juc 高级并发编程包,ConcurrentHashMap<K,V>-->推荐

 */
public class Class001_Collections {
    public static void main(String[] args) {
        /*
            void sort(List)  //对List容器内的元素排序,排序的规则是按照升序进行排序。
            void shuffle(List) //对List容器内的元素进行随机排列
            void reverse(List) //对List容器内的元素进行逆续排列
            void fill(List, Object)  //用一个特定的对象重写整个List容器
            int binarySearch(List, Object)//对于顺序的List容器,采用折半查找的方法查找特定对象
         */
        List<Integer> list = new ArrayList<>();

        list.add(3);
        list.add(1);
        list.add(2);
        list.add(5);
        list.add(4);

        System.out.println(list);

        //sort 升序排序徐
        Collections.sort(list);
        System.out.println(list);

        //sort(List<T> list, Comparator<? super T> c)

        //shuffle 随机排序
        //Collections.shuffle(list);
        System.out.println(list);

        //void reverse(List)翻转
        //Collections.reverse(list);
        System.out.println(list);

        //binarySearch  如果找到返回索引,找不到返回-插入点-1
        System.out.println(Collections.binarySearch(list,12));
    }
}

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值