Hashset

Hashset

HashSet 无序,去重

​ 底层结构: 哈希表(数组+链表+红黑树)

​ 特点:
​ 做查询,增删效率较高
​ 无序去重

​ 初始容量: 16
​ 加载因子: 0.75 ->扩容的临界点

​ 扩容的临界点 = 容量加载因子;
​ 12 = 16
0.75; 当存储的数据到12就扩容

HashSet 与 TreeSet之间的选择
如果想要数据存储的时候默认升序|降序->TreeSet
否则建议选择HashSet

构建一个HashSet 存储字符串类型的数据,做基本操作行为,然后遍历
构建一个HashSet 存储自定义引用数据类型的数据,做基本操作行为,然后遍历

TreeSet

TreeSet
默认升序,去重
红黑树

当方法|构造器参数为接口类型的时候,实参可以考虑是否可以通过一个Lambda表达式进行传递

lambda可以让行为作为参数|数据传递,配合函数式接口,可以让定义与实现变的更加简单灵活

Arrays工具类 操作数组的工具类
练习:
定义一个User类型的数组,使用Arrays.sort方法对这个数据做升序排序
排序规则: 要求按照用户编号降序排序
排序规则: 要求按照用户员工的余额升序排序
分别打印
static void sort 根据元素的natural ordering ,将指定的对象数组按升序排序。
static void sort 根据指定比较器引发的顺序对指定的对象数组进行排序。

public class SetDemo01 {
    public static void main(String[] args) {
        //匿名内部类   简化实现类IMPL
        Comparator<Person> com = new Comparator<Person>(){

            @Override
            public int compare(Person o1, Person o2) {
                return o2.getAge() - o1.getAge();
            }
        };

        //Lambda
        com = (Person o1, Person o2)->{
            return o1.getAge() - o2.getAge();
        };

        //指定使用外部比较规则
        //TreeSet<Person> tree= new TreeSet<Person>(com);
        TreeSet<Person> tree= new TreeSet<Person>((Person o1, Person o2)->{
            return o1.getAge() - o2.getAge();
        });

        tree.add(new Person("胡歌",35));
        tree.add(new Person("大表哥",30));
        tree.add(new Person("金城武",34));
        tree.add(new Person("谢霆锋",30));

        System.out.println(tree);



    }
}

//外部比较器
class Impl implements Comparator<Person>{

    @Override
    public int compare(Person o1, Person o2) {
        return o1.getAge() - o2.getAge();
    }
}

LinkedList

LinkedList 有序可重复
底层结构: 双向链表
特点:
增删效率较高
根据索引查询,遍历,修改效率低
应用场景: 在大量做增删,少量做查询的位置适合使用LinkedList

​ 新增: 新增了一些操作链表头尾的方法

​ 练习: 使用LinkedList存储自定义引用数据类型的数据,并操作练习

public class ListDemo01 {
    public static void main(String[] args) {
        LinkedList<String> linked = new LinkedList<>();
        linked.add("haha");
        linked.add("hehe");
        linked.add("heihei");
        linked.add("houhou");
        linked.add("xixi");
        //新增方法
        //void addFirst(E e) 在此列表的开头插入指定的元素。
        //void addLast(E e) 将指定的元素追加到此列表的末尾。
        System.out.println(linked);

        linked.addFirst("first");
        linked.addLast("last");
        System.out.println(linked);

        //E element() 检索但不删除此列表的头部(第一个元素)。
        System.out.println(linked.element());
    }
}
/*
    手写LinkedList
        使用单向链表实现

        思考实现:
            根据索引修改,查询
 */
public class MyLinkedListDemo02 {
    public static void main(String[] args) {
        MyLinkedList list = new MyLinkedList();

        //list.add("数据");
        System.out.println(list.size());
        //list.add("haha");
        System.out.println(list.size());
        System.out.println(list);
    }
}

//自定义容器类型: MyLinkedList
class MyLinkedList{
    //链表头节点
    private Node head;
    //长度
    private int size;

    public MyLinkedList() {
    }

    /*
        添加
     */
    public void add(Object value) {
        //创建新节点
        Node node = new Node(value,null);
        //判断是不否存在链表头节点
        if(head==null && size==0){
            head = node;  //新节点就是链表头节点
        }else{
            //存在原链表,遍历原链表,找到最后一个节点,新节点的地址记录
            Node temp = head;  //temp指向链表头节点,后面使用temp操作遍历指向每一个节点,直到最后一个
            while(temp.getNext()!=null){
                temp = temp.getNext();
            }
            temp.setNext(node);  //把新节点挂在原链表的最后
        }
        size++;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("[");
        //1.临时变量,指向链表中的每一个节点
        Node temp = head;

        //获取每一个节点的值value
        while(true){
            //结束条件
            if(temp==null){
                break;
            }
            sb.append(temp.getValue()); //数据的拼接
            sb.append(","); //数据的拼接
            temp = temp.getNext();  //指向新节点

        }
        //StringBuilder replace(int start, int end, String str) 使用指定的 String的字符替换此序列的子字符串中的字符。
        if(sb.length()==1){
            sb.append("]");
        }else{
            sb.replace(sb.length()-1,sb.length(),"]");
        }
        //拼接成字符串返回
        return sb.toString();
    }

    public int size(){
        return this.size;
    }
}

//节点
class Node{
    private Object value;  //数据
    private Node next;  //下一个节点对象的地址

    public Node() {
    }

    public Node(Object value, Node next) {
        this.value = value;
        this.next = next;
    }

    public Object getValue() {
        return value;
    }

    public void setValue(Object value) {
        this.value = value;
    }

    public Node getNext() {
        return next;
    }

    public void setNext(Node next) {
        this.next = next;
    }

    @Override
    public String toString() {
        return "Node{" +
                "value=" + value +
                ", next=" + next +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Node node = (Node) o;
        return Objects.equals(value, node.value) &&
                Objects.equals(next, node.next);
    }

}

HashMap

HashMap
HashSet --> HashMap
底层结构:
哈希表(数组+链表+红黑树)
特点:
存储键值对类型数据
无序,根据key做去重
查询,修改,删除,增加效率较高

Hash表存储原理:
哈希表: Node节点数组,存储节点数据 节点:key,value,hash,next
1.put(key,value)存储键值对类型的数据
根据key计算hash值,确定桶的位置
2.找到Node数组中的指定索引位置,判断当前位置中是否存在数据,没有存在直接构建一个Node节点对象 new Node(key,value,hash,null),放入数组
如果已经存在值,就比较每一个Node的key与我当前要存储的key是否相等,相等value覆盖,不相等继续判断,最后数据放入链表的最后

默认初始容量: 1<<4 16-> 数组长度
加载因子 : 0.75
最大容量… 1<<30
扩容: 新数组的容量为原容量的2倍 newCap = oldCap << 1
当添加的数据个数>=原数组长度*0.75的时候,就扩容,扩容的是数组的大小

HashMap存储key如果为自定义引用数据类型:
key去重的问题 : key类型中要求重写hashcode与equals方法

Map<K,V>
接口
存储键值对的数据
k-v 一个映射关系
key->value
key与value可以为任意类型的一个数据
一个key只能对应一个value
key是唯一的,无序的 --> Set集合
value是无序可重复的 --> Collection 无序可重复

遍历方式:
Set keySet() 返回所有的key,通过key获取value
Collection values() 获取集合中的所有value值,无法获取key
Set<Map.Entry<K,V>> entrySet()

public class MapDemo01 {
    public static void main(String[] args) {
        Map<Integer,String> map = new HashMap<>();
        //V put(K key, V value)  添加一个键值对数据,如果key重复,value会覆盖,返回被覆盖的value值,如果key不重复,返回null
        System.out.println(map.put(101,"张三"));
        System.out.println(map.put(103,"wangwu"));
        System.out.println(map.put(102,"lisi"));
        System.out.println(map.put(101,"zhangsan"));
        System.out.println(map.put(104,"zhangsan"));

        System.out.println(map);

        //V get(Object key)  根据key获取value,没有返回null
        System.out.println(map.get(108));


        //int size()
        System.out.println(map.size());

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

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

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

        //default boolean replace(K key, V oldValue, V newValue) 仅当前映射到指定值时,才替换指定键的条目。
        System.out.println(map.replace(101,"zhangsan","hahaha"));
        System.out.println(map);

        //遍历
        System.out.println("-------- Set<K> keySet()  返回所有的key,通过key获取value-------------");
        Set<Integer> set = map.keySet();
        //1)foreach   2)iterator
        for(Integer t:set){
            System.out.println(t+"-->"+map.get(t));


        }
        System.out.println("-------------Collection<V> values() 获取集合中的所有value值,无法获取key------");
        Collection<String> col = map.values();
        //1)foreach   2)iterator
        Iterator<String> it = col.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }

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

    }

}
public class MapDemo02 {
    public static void main(String[] args) {
        Map<Integer,String>  map  =  new HashMap<>();
        System.out.println(map.put(100,"张三"));
        System.out.println(map.put(102,"李四"));
        System.out.println(map.put(103,"王五"));
        System.out.println(map.put(104,"赵六"));
        System.out.println(map.put(105,"田七"));
        System.out.println(map.put(106,"勾八"));
        System.out.println(map);

        System.out.println(map.get(100));

        System.out.println(map.size());


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

        //default boolean replace(K key, V oldValue, V newValue) 仅当前映射到指定值时,才替换指定键的条目。
        System.out.println(map.replace(103,"王五","牛逼"));
        System.out.println(map);

        //遍历
        System.out.println("-------- Set<K> keySet()  返回所有的key,通过key获取value-------------");

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

        }
        System.out.println("-------------Collection<V> values() 获取集合中的所有value值,无法获取key------");
        Collection<String> col = map.values();

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

        System.out.println("------- Set<Map.Entry<K,V>> entrySet() ------------");

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

        }



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值