Java基础(集合学习总结)

一、链表结构

1.1 单链表的结构

所谓单链表(Linked)在内存中不连续的一端内存空间, 链表的每一个元素是一个节点,每一个结点由数据元素和下一个结点的存储位置组成,链表结构与数组结构最大区别是链接结构的存储内存是不连续的,而数组结构的内存是连续的,链表结构不能与数组结构一样快速查找。

  1. 链表结构操作特点是 添加,删除元素效率高,查询效率低 ​
  2. 数组结构操作特点: 添加,删除效率低,查询效率高
    前驱: 该节点的上一个元素的地址
    后继: 该节点的下一个元素的地址
    链表结构中最后一个元素的”后继“为null

1.2 单链表的实现

public class Test1 {
    int size;
    Node header;
    class Node<T> {
        T date;
        Node next;   //下一个节点的地址
        public Node(T date) {
            this.date = date;
        }
        public T getDate() {
            return date;
        }
        public void setDate(T date) {
            this.date = date;
        }
        public Node getNext() {
            return next;
        }
        public void setNext(Node next) {
            this.next = next;
        }
    }
    //添加到首节点
    public void addFirst(Object obj) {
        //创建节点
        Node node = new Node(obj);
        //将当前链表的头节点变更为新节点
        //新节点中的后继是原始头节点
        node.next = this.header;
        //将头节点变更
        this.header = node;
        //长度+1
        this.size++;
    }
    //删除第一个节点
    public void removeFirst() {
        if (this.size == 0) {
            throw new IllegalArgumentException("没有需要删除的元素");
        }
        Node node = this.header.next;  //获取当前节点连接的后继
        this.header = node;
        this.size--;
    }
    //删除最后一个元素
    public void deleteLast(){
        if (this.size==0){
            throw new IllegalArgumentException("没有需要删除的元素");
        }else if (this.size==1){
            removeFirst();
        }else if (size==2){
            this.header.next=null;
        }else{
            Node lastNode=this.header;  //将第一个节点初始为最后一个节点
            for (int i = 0; i <size-2 ; i++) {
                lastNode=lastNode.next;
            }
            lastNode.next=null;
        }
        this.size--;
    }
    //给指定位置添加节点
    public void addNode(Object obj, int index) {
        Node node = new Node(obj);
        if (index < 0 || index >= this.size) {   //当添加的元素下标大于当前链表的长度时,抛出异常
            throw new IllegalArgumentException("下标越界");
        }
        if (index == 0) {
            addFirst(obj);
        } else {
            Node pre = this.header;  //前一个下标节点
            Node cur;
            for (int i = 0; i < index - 1; i++) {
                pre = pre.next;
            }
            cur = pre.next;
            pre.next = node;
            node.next = cur;
            this.size++;
        }
    }
    public Node getByIndex(int index) {
        if (this.size == 0) {
            throw new IllegalArgumentException("没有需要查找的元素");
        }
        if (index == 0) {
            return this.header;
        }
        // 查找指定下标的元素(放在)
        Node cur = this.header;  // 从第一个元素开始
        int j = 0;
        while (index != j && index < this.size) {
            // 依次往下一个元素查找
            cur = cur.next;
            j++;
        }
        return cur;
    }
    public void addLast(Object obj) {
        //将节点添加到最后
        //创建节点
        Node node = new Node(obj);
        if (this.size == 0) {
            addFirst(obj);
        } else {
            //找最后一个节点(由于最后一个节点的next是null)
            Node lastNode = this.header;   //将头节点初始为最后一个节点
            while (lastNode.next != null) {//往后遍历将节点的前驱变为后继
                lastNode = lastNode.next;
            }
            lastNode.next = node;   //将原来最后一个节点的后继变为当前创建的节点的前驱
            this.size++;  //添加一个元素链表长度加一
        }
    }

2、队列结构

队列结构(Queue): 在基于链表结构的基础上 ,实现的一种“先进先出”的结构, 常用操作 入队(put),出队(pop) ,设置队列的头结点 和 尾结点 。

3、栈结构

栈(Stack)结构也是常用数据结构之一,它具有 “后进先出” 的特点。

二、LinkedList集合

  1. java.util.LinkedList集合是java.util.List的实现类,实现List接口的所有方法(添加,删除,查找,判断是空等)它添加,删除元素较快,查询相对慢,但是查询头尾元素较快。
  2. LinkedList集合实现双向链表接口,实现从头元素到尾元素的链表和从尾到头元素的链表,目标为了增加元素的检索效率 。
    关于LinkedList实现大量操作头元素和尾元素的方法。 其中必须通过LinkedList的引用创建该对象
    public void addFirst(E e) :将指定元素插入此列表的开头。
    public void addLast(E e) :将指定元素添加到此列表的结尾。
    public E getFirst() :返回此列表的第一个元素。
    public E getLast() :返回此列表的后一个元素。
    public E removeFirst() :移除并返回此列表的第一个元素。
    public E removeLast() :移除并返回此列表的后一个元素。
    public E pop() :从此列表所表示的堆栈处弹出一个元素。
    public void push(E e) :将元素推入此列表所表示的堆栈。
    public boolean isEmpty() :如果列表不包含元素,则返回true

三、 Set集合

​ java.util.Set 接口 继承自Collection接口,实现对元素的基本操作 ,与java.util.List区别于 Set集合存储无序,且唯一的元素,List存储有序,且可重复的元素
​ Set接口的实现类 HashSet 、 LinekedHashSet 、TreeSet

1、HashSet

​ HashSet集合依据元素的哈希值确定在内存中的存储位置, 所谓Hash值是内存中哈希表的唯一标志,通过哈希值可快速检索到元素所在的位置 , 所以它查询效率高 ,与HashSet类似结构的包括HashMap 等
​ 创建一个HashSet时,就是创建一个HasMap( 关于HashMap结构后面讲)
​ 什么是哈希表?
在Java1.8以前,哈希表的底层实现采用数组+链表结构,但是这样对于“Hash冲突” (两个对象生成的哈希值一样),即多个元素存储在一个“数据桶”中, 这样查找该元素时,依然效率低下, 为了解决由于哈希冲突导致的数据查询效率低下,JDK8以后将哈希表实现采用 数组+链表+红黑树结构

1.2.HashSet存储自定义对象类型

​ HashSet对于对象是否相同的依据,判断对象的hashCode值和equals是否相等,如果它们相等则判断元素一致,不能重复添加。
注:但是需要重写equals和hashcode方法。

1.3 LinkedHashSet

​ 在HashSet中存储的数据是唯一且无序,如何保证数据的有序型,可通过扩展HashSet的子类完成,
java.util.LinkedHashSet ,它实现有序的Hash结构, 它的底层实现使用链表+哈希结构
创建LinkedHashSet时,就是创建一个LinkedHashMap结构 ,linkeHashSet中如何保证顺序一致性
​ accessOrder = false; 按照插入的顺序存储 accessOrder = true: 按照访问的顺序存储。

 // 创建LinkedHashSet对象
        ,LinkedHashSet<String> set = new LinkedHashSet();
        set.add("aaa");
        set.add("bbb");
        set.add("ccc");
        set.add("ddd");
        //遍历元素
        for(String s : set){
            System.out.println(s);
        }

1.4 TreeSet (默认按升序排序,元素不重复)

TreeSet实现对Set元素的排序功能, 也包含基础的Set集合功能。 存放在TreeSet中的元素时有序的,默认升序,也可以自定义排序规则。
两种方式实现自定义排序规则
1、对元素(自定义类)实现 java.lang.Comparable 接口,重写 compareTo方法:

public class Fruit  implements  Comparable<Fruit>{
    private  int id;
    private String name;
    public int compareTo(Fruit o) {
            // return this.id-o.id;  升序
        return  o.id - this.id;
            // 正数: 前一个大于后一个
            // 负数: 前一个小于后一个
    }
 }
  // 实现自定义排序规则的方式一 :  对象实现Comparable接口 (java.lang)
        // 重写compareTo 方法。
        TreeSet<Fruit> fruitSet = new TreeSet<>();
        Fruit f1 = new Fruit(100,"苹果");
        Fruit f2 = new Fruit(101,"香蕉");
        fruitSet.add(f1);
        fruitSet.add(f2);
        System.out.println(fruitSet.size());
        for(Fruit f : fruitSet){
            System.out.println(f.getId()+"---"+f.getName());
        }

2、通过匿名内部类的方式 在创建TreeSet时,创建自定义排序规则 ,new Comparator的接口

// 自定义排序规则的方式二: 对treeSet实现匿名内部类  new Comparator(java.util)
        TreeSet<Integer> scores  = new TreeSet (new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2-o1;  //降序
            }
        });
        //  添加元素
        scores.add(80);
        scores.add(87);
        scores.add(90);
        scores.add(78);
        for(Integer score :  scores){
            System.out.println(score);
        }
// 按照对象的某一属性降序(重写排序方法)
        TreeSet<People> peopleSet = new TreeSet<>(new Comparator<People>() {
            @Override
            public int compare(People o1, People o2) {
                return o2.getAge()- o1.getAge(); // 根据age降序排列
            }
        });
        peopleSet.add(new People(1001,"张飞",100));
        peopleSet.add(new People(1002,"刘备",102));
        peopleSet.add(new People(1003,"关羽",108));
        for(People p : peopleSet){
            System.out.println(p.getPid()+"--"+p.getAge());
        }

三、Map集合

java.util.Map集合用于存储key-value的数据结构 ,一个键对应一个值,其中键在集合中是唯一的, Value可以重复, 例如 学号与学生的关系,省份编号对应省份信息, 对于Map集合的常用实现类包括 HashMap 、LinkedHashMap、HashTable 、TreeMap 等 。

1、HashMap(重点)

​ java.util.HashMap 存储无序的,键值对数据,HashMap的实现原理在JDK1.8以前使用 链表+数组结构,1.8以后使用链表+数组+红黑树结构, 使用Hash表的存储方式其检索效果高
​ 特点:
​ a、HashMap的key唯一,且无序,value不唯一
​ b、HashMap的key和value 都可以为null
​ c、对于相同key 元素,它的value会覆盖原始value
​ HashMap的常用方法:

HashMap() 
构造一个空的 HashMap ,默认初始容量(16)和默认负载系数(0.75)。  
HashMap(int initialCapacity) 
构造一个空的 HashMap具有指定的初始容量和默认负载因子(0.75)。  
HashMap(int initialCapacity, float loadFactor) 
构造一个空的 HashMap具有指定的初始容量和负载因子。  
HashMap(Map<? extends K,? extends V> m) 
构造一个新的 HashMap与指定的相同的映射 Map 。 

a、put(K key,V value) : 存储key-value 到容器中
b、V get(K key): 根据key 获取对应的value
c、Set keySet(): 返回所有的key,Set集合
d、boolean containsKey(K key): 判断key是否存在
e、clear():清空容器的原始
f、boolean containsValue(V value):判断value是否存在
g、Collection values() : 返回所有的value集合
h、isEmpty(): 判断是否为空集合
i、remove(Object key) : 根据key删除这个key-value
j、size():返回元素的大小
k、Set<Map.Entry<Key,Value>> entrySet(): 返回容器的key-value的实体类的集合,方便遍历元素
注:要了解底层源码。

集合里面常见的问题:

1、Collection 和 Collections 的区别? Array 和Arrays的区别?

  • ​ Collection是集合的顶级接口 ,Collections是一个集合工具类 ,它提供大量的操作集合方法,例如排序, 打乱顺序,添加元素等。
  • ​ Array 表示一个数组对象 , Arrays是一个数组工具类 ,提供大量的数组操作方法。

2、List 和 Set 的区别? ArrayList 和 LinkedList的区别

  • ​ 相同点:List、Set 都继承Collection接口
  • ​ 不同点: List 存储不唯一,有序集合元素 , Set 存储唯一,无序的集合元素
  • ​ ArrayList 实现数组结构集合,查询比较快,添加,删除效率低
  • ​ LinkedList实现双向链表结构集合,添加,删除效率高, 查询效率低

3、HashSet 和 TreeSet的区别?

  • 它们都存储唯一集合,都实现Set接口
  • HashSet无序,底层实现Hash结构的存储, TreeSet有序,可实现自定义排序,存储树形结构

4、HashMap 和 HashSet的区别?

  • 它们都属于Hash结构的集合,存储效率较高 , HashSet是存储单个元素 ,HashMap存储键值对元素
  • HashMap实现Map接口,HashSet实现Set接口 ,

5、HashMap 和HashTable的区别

  • 它们都来自Map 的实现类, HashTable 还继承一个父类 Dictionary
  • HashMap 的key和value 可以为空,HashTable 的key value 不能为空;
  • HashTable 的子类包含key value 的方法
  • HashMap线程不安全效率高 ,HashTable线程安全效率低

6、HashMap 和 TreeMap的区别?

  • ​ 它们都实现Map接口 ,TreeMap 有序,HashMap无序, HashMap实现哈希结构 集合,TreeMap实现二叉树集合。
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值