IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java学习笔记-集合 -> 正文阅读

[Java知识库]Java学习笔记-集合

资料

  1. 参考博文:https://blog.csdn.net/weixin_44176393/article/details/110367870
  2. 参考:https://www.runoob.com/java/java-collections.html
  3. 参考:https://www.liaoxuefeng.com/wiki/1252599548343744/1265112034799552

学习目标

  1. 了解集合类的基本架构
  2. 了解ArrayList、LinkedList的用法、优缺点
  3. 了解Set的用法、优缺点
  4. 了解Map、TreeMap、HashMap的用法、优缺点
  5. 了解常用数据结构

基础知识

集合就是“由若干个确定的元素所构成的整体”,对象的容器,定义了对多个对象进行操作的常用方法,可实现数组的功能。

集合框架图:
在这里插入图片描述
削减版的架构图:
在这里插入图片描述
集合和数组的区别:

  • 数组长度固定,集合长度不固定
  • Java集合如Map、Set、List等所有集合只能存放引用类型数据,它们都是存放引用类型数据的容器,不能存放如int、long、float、double等基础类型的数据。 可以通过包装类把基本类型转为对象类型,存放引用就可以解决这个问题。

Collection

Java标准库自带的java.util包提供了集合类:Collection,它是除Map外所有其他集合类的根接口。Java的java.util包主要提供了以下三种类型的集合:

  • List:一种有序列表的集合,允许重复元素
  • Set:一种保证没有重复元素的集合,无序集合
  • Map:一种通过键值(key-value)查找的映射表集合

集合常用方法:

1boolean add(Object obj):添加一个对象
2boolean addAll(Collection c):将一个集合中的所有对象添加到此集合中
3void clear():清空此集合中的所有对象
4boolean contains(Object o):检查此集合中是否包含o对象
5boolean equals(Object o):比较此集合是否与指定对象相等
6boolean isEmpty():判断此集合是否为空
7boolean remove(Object o):在此集合中移除o对象
8int size():返回此集合中的元素个数
9、Object[ ] toArray():将此集合转换成数组
10、Iterator< > iterator():返回在此collection的元素上进行迭代的迭代器

示例代码:

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class Demo01 {
    public static void main(String[] args) {
        //创建集合
        Collection collection = new ArrayList();
        //添加元素
        collection.add("苹果");
        collection.add("香蕉");
        collection.add("梨");
        System.out.println("元素个数:"+collection.size());
        System.out.println(collection);

        //删除元素
        collection.remove("香蕉");
        System.out.println("删除之后元素个数:"+collection.size());

        //遍历(重点)
        //1.使用增强for(foreach)
        for (Object object: collection
             ) {
            System.out.println(object);
        }
        System.out.println("-----------------------------");
        //2.使用迭代器(迭代器专门用来遍历集合的一种方式)
        //haNext(); 仍有元素可以迭代 返回true
        //next(); 获取下一个元素
        //remove(); 移除当前元素
        Iterator it = collection.iterator();
        //迭代过程中不允许使用collection.remove方法 可以用it.remove
        while(it.hasNext()){//hasNext()判断是否有下一个元素
            String s = (String)it.next();//next()返回下一个元素
            System.out.println(s);
            it.remove();
        }
        System.out.println("当前元素:"+collection.size());
        System.out.println("----------------");
        //判断
        System.out.println(collection.contains("西瓜"));
        System.out.println(collection.isEmpty());
    }
}


package study.gather.Demo01;

import java.util.ArrayList;
import java.util.Collection;

public class Demo02 {
    public static void main(String[] args) {
        //新建collection对象 和 学生对象
        Collection collection = new ArrayList();
        Student s1 = new Student("张三", 20);
        Student s2 = new Student("李四", 25);
        Student s3 = new Student("王五", 24);
        //添加数据
        collection.add(s1);
        collection.add(s2);
        collection.add(s3);
        System.out.println("元素个数:"+collection.size());
        System.out.println(collection.toString());

        //删除
        collection.remove(s1);
        System.out.println("元素个数:"+collection.size());
        //清空
        collection.clear();//只是在将对象在集合里移除了 但是对象并没有消失
        
        
    }
}

重写equals方法

如何正确编写equals()方法?equals()方法要求我们必须满足以下条件:

  • 自反性(Reflexive):对于非null的x来说,x.equals(x)必须返回true;
  • 对称性(Symmetric):对于非null的x和y来说,如果x.equals(y)为true,则y.equals(x)也必须为true;
  • 传递性(Transitive):对于非null的x、y和z来说,如果x.equals(y)为true,y.equals(z)也为true,那么x.equals(z)也必须为true;
  • 一致性(Consistent):对于非null的x和y来说,只要x和y状态不变,则x.equals(y)总是一致地返回true或者false;
  • 对null的比较:即x.equals(null)永远返回false。

我们总结一下equals()方法的正确编写方法:

  • 先确定实例“相等”的逻辑,即哪些字段相等,就认为实例相等;
  • instanceof判断传入的待比较的Object是不是当前类型,如果是,继续比较,否则,返回false
  • 对引用类型用Objects.equals()比较,对基本类型直接用==比较。
  • 使用Objects.equals()比较两个引用类型是否相等的目的是省去了判断null的麻烦。两个引用类型都是null时它们也是相等的。
  • 如果不调用Listcontains()indexOf()这些方法,那么放入的元素就不需要实现equals()方法。

示例代码:

import java.util.List;
import java.util.Objects;

public class HelloWord {
    public static void main(String[] args) {
        List<Person> list = List.of(
                new Person("Xiao", "Ming", 18),
                new Person("Xiao", "Hong", 25),
                new Person("Bob", "Smith", 20)
        );
        boolean exist = list.contains(new Person("Bob", "Smith", 20));
        System.out.println(exist ? "测试成功!" : "测试失败!");
    }
}

class Person {
    String firstName;
    String lastName;
    int age;
    public Person(String firstName, String lastName, int age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.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(firstName, person.firstName) && Objects.equals(lastName, person.lastName);
    }

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

List

在集合类中,List是最基础的一种集合:它是一种有序列表
List的行为和数组几乎完全相同:List内部按照放入元素的先后顺序存放,每个元素都可以通过索引确定自己的位置,List的索引和数组一样,从0开始。

ArrayList

在这里插入图片描述
引用包:

import java.util.ArrayList;

创建方法:

ArrayList<T> arrayList = new ArrayList<T>();

示例代码:

import java.util.ArrayList;
import java.util.Comparator;

public class RunoobTest {
    public static void main(String[] args) {
        ArrayList<String> sites = new ArrayList<String>();
        //添加元素
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Weibo");
        System.out.println(sites);
        //访问元素
        System.out.println(sites.get(1));  // 访问第二个元素
        //修改元素
        sites.set(2, "Wiki"); // 第一个参数为索引位置,第二个为要修改的值
        System.out.println(sites);
        //删除元素
        sites.remove(3); // 删除第四个元素
        System.out.println(sites);
        //获取List长度
        System.out.println(sites.size());
        //循环输出元素
        for (int i = 0; i < sites.size(); i++) {
            System.out.println(sites.get(i));
        }  
        for (String i : sites) {
            System.out.println(i);
        }
        //List排序
        sites.sort(Comparator.naturalOrder());
        System.out.println("排序后: " + sites);              
    }
}

List转Array:

import java.util.List;

public class HelloWord {
    public static void main(String[] args) {
        List<String> list = List.of("apple", "pear", "banana");
        //第1种方法
        Object[] array = list.toArray();
        for (Object s : array) {
            System.out.println(s);
        }
		//第2种方法,指定类型
        String[] stringArray1 = list.toArray(new String[3]);
        for (String n : stringArray1) {
            System.out.println(n);
        }
		//第2种方法改进版
        String[] stringArray2= list.toArray(new String[list.size()]);
        for (String n : stringArray2) {
            System.out.println(n);
        }
		//第3种方法
        String[] stringArray3 = list.toArray(String[]::new);
        for (String n : stringArray3) {
            System.out.println(n);
        }
    }
}

Array变List

import java.util.List;

public class HelloWord {
    public static void main(String[] args) {
    	//Array变为List就简单多了,通过List.of(T...)方法
        List<Integer> list = List.of(12, 34, 56);
        System.out.println(list);
        //我们调用List.of(),它返回的是一个只读List,如下代码会报错
        list.add(999); // UnsupportedOperationException
    }
}

常用API:

方法描述
add()将元素插入到指定位置的 arraylist 中
addAll()添加集合中的所有元素到 arraylist 中
clear()删除 arraylist 中的所有元素
clone()复制一份 arraylist
contains()判断元素是否在 arraylist
get()通过索引值获取 arraylist 中的元素
indexOf()返回 arraylist 中元素的索引值
removeAll()删除存在于指定集合中的 arraylist 里的所有元素
remove()删除 arraylist 里的单个元素
size()返回 arraylist 里元素数量
isEmpty()判断 arraylist 是否为空
subList()截取部分 arraylist 的元素
set()替换 arraylist 中指定索引的元素
sort()对 arraylist 元素进行排序
toArray()将 arraylist 转换为数组
toString()将 arraylist 转换为字符串
ensureCapacity()设置指定容量大小的 arraylist
lastIndexOf()返回指定元素在 arraylist 中最后一次出现的位置
retainAll()保留 arraylist 中在指定集合中也存在的那些元素
containsAll()查看 arraylist 是否包含指定集合中的所有元素
trimToSize()将 arraylist 中的容量调整为数组中的元素个数
removeRange()删除 arraylist 中指定索引之间存在的元素
replaceAll()将给定的操作内容替换掉数组中每一个元素
removeIf()删除所有满足特定条件的 arraylist 元素
forEach()遍历 arraylist 中每一个元素并执行特定操作

小结:

  1. ArrayList必须要连续空间,查询快、增删慢
  2. 频繁访问列表中的某一个元素时使用ArrayList。
  3. 只需要在列表末尾进行添加和删除元素操作时使用ArrayList。

LinkedList

链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的地址。链表可分为单向链表和双向链表。

一个单向链表包含两个值: 当前节点的值和一个指向下一个节点的链接。
在这里插入图片描述
一个双向链表有三个整数值: 数值、向后的节点链接、向前的节点链接。
在这里插入图片描述
以下情况使用 LinkedList :

  • 你需要通过循环迭代来访问列表中的某些元素。
  • 需要频繁的在列表开头、中间、末尾等位置进行添加和删除元素操作。

LinkedList 继承了 AbstractSequentialList 类。
LinkedList 实现了 Queue 接口,可作为队列使用。
LinkedList 实现了 List 接口,可进行列表的相关操作。
LinkedList 实现了 Deque 接口,可作为队列使用。
LinkedList 实现了 Cloneable 接口,可实现克隆。
LinkedList 实现了 java.io.Serializable 接口,即可支持序列化,能通过序列化去传输
在这里插入图片描述
引用包:import java.util.LinkedList;
创建方法:

LinkedList<E> list = new LinkedList<E>();   // 普通创建方法
或者
LinkedList<E> list = new LinkedList(Collection<? extends E> c); // 使用集合创建链表

示例代码:

import java.util.LinkedList;

public class HelloWord {
    public static void main(String[] args) {
        LinkedList<String> sites = new LinkedList<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Weibo");
        // 使用 addFirst() 在头部添加元素
        sites.addFirst("Baidu");
        // 使用 addLast() 在尾部添加元素
        sites.addLast("Alibaba");
        for (int size = sites.size(), i = 0; i < size; i++) {
            System.out.println(sites.get(i));
        }
        // 使用 removeFirst() 移除头部元素
        sites.removeFirst();
        // 使用 removeLast() 移除尾部元素
        sites.removeLast();
        for (String i : sites) {
            System.out.println(i);
        }
        // 使用 getFirst() 获取头部元素
        System.out.println(sites.getFirst());
        // 使用 getLast() 获取尾部元素
        System.out.println(sites.getLast());
    }
}

常用方法:传送门
小结:

  1. API
    1. 首尾添加
    2. 首尾获取
    3. 首尾移除
  2. (双向)链表结构:
    1. 每一个元素都分为上一个,下一个,当前元素
    2. 每次增加元素,只新增一个对象,极大提高了集合元素变化的性能
    3. 对元素的访问性能不高,因为其本质是没有游标的,要访问某个元素都是从首尾开始迭代

Set

如果我们只需要存储不重复的key,并不需要存储映射的value,那么就可以使用Set
特点:

  • 无序、无下标、元素不可重复
  • Set实现了Collection接口中定义的方法。

Set用于存储不重复(唯一)的元素集合,它主要提供以下几个方法:

  • 将元素添加进Set:boolean add(E e)
  • 将元素从Set删除:boolean remove(Object e)
  • 判断是否包含元素:boolean contains(Object e)

Set实际上相当于只存储key、不存储value的Map。我们经常用Set用于去除重复元素。
在这里插入图片描述
Set接口并不保证有序,而SortedSet接口则保证元素是有序的:

  • HashSet是无序的,因为它实现了Set接口,并没有实现SortedSet接口;
  • TreeSet是有序的,因为它实现了SortedSet接口。

HashSet

没有真正意义上的set集合,他使用的是HashMap的key。
方法:

  • 新建集合 HashSet<String> hashSet = new HashSet<String>();
  • 添加元素 hashSet.add( );
  • 删除元素 hashSet.remove( );
  • 遍历操作
    增强for for(type type : hashSet)
    迭代器 Iterator<String> it = hashSet.iterator( );
  • 判断 hashSet.contains( );hashSet.isEmpty();

TreeSet

特点:

  • 基于排列顺序实现元素不重复
  • 实现SortedSet接口,对集合元素自动排序
  • 元素对象的类型必须实现Comparable接口,指定排序规则
  • 通过CompareTo方法确定是否为重复元素
  • 使用TreeSet和使用TreeMap的要求一样,添加的元素必须正确实现Comparable接口,如果没有实现Comparable接口,那么创建TreeSet时必须传入一个Comparator对象。

方法:

  • 创建集合 TreeSet treeSet = new TreeSet<>()
  • 添加元素 treeSet.add();
  • 删除元素 treeSet.remove();
  • 遍历 1. 增强for 2. 迭代器
  • 判断 treeSet.contains();

使用:要求:元素必须实现Comparable接口,compareTo()方法的返回值为0,认为是重复元素

// 重写compareTo
@override
public int compareTo(Person o){
  int n1 = this.getName().compareTo(o.getName());  //后面的compareTo方法为String带的方法
  int n2 = this.getAge()-o.getAge();
  return n1 == 0 ? n2 : n1;
}

或者 传入一个Comparator对象

// 重写compare  创建集合时就制定比较规则
TreeSet<Person> treeSet = new TreeSet<>(new Comparator<Person>){
    @override
    public int compare(Person o1,Person o2){
      int n1 = o1.getName().compareTo(o2.getName());  
      int n2 = o1.getAge()-o2.getAge();
      return n1 == 0 ? n2 : n1;
    }
}

Map

特点:存储一对数据(Key-Value)【键值对】,无序、无下标、键不可重复,值可重复

HashMap

在这里插入图片描述
方法:

  • V put(K key,V value):将对象存入到集合中,关联键值。key重复则覆盖原值
  • Object get(Object key):根据键获取对应的值
  • keySet():返回所有key
  • values():返回包含所有值的Collection集合
  • Set<Map.Entry<K,V>> entrySet():键值匹配的Set集合
  • boolean containsKey(K key):判断key是否存在

示例代码:

import java.util.HashMap;
import java.util.Map;

public class HelloWord {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();//需要指定key和value的类型
        // 1. 添加元素
        map.put("cn", "中国");
        map.put("uk", "英国");
        map.put("cn", "zhongguo"); // 会替换第一个
        // 2. 删除
        map.remove("uk"); //用key删除
        // 3. 遍历
        // 3.1 使用KeySet()
        for(String key : map.keySet()){
            System.out.println(key + "---" + map.get(key));
        }
        // 3.2 使用entrySet()
        for(Map.Entry<String, String> entry : map.entrySet()){
            System.out.println(entry.getKey() + "---" + entry.getValue());
        }
        //判断
        System.out.println(map.containsKey("cn"));
        System.out.println(map.containsValue("泰国"));
    }
}

备注:Java这块的Map和C#中的Dictionary不太一样,如果key已经存在了再添加同名的key不会报错。

重复放入key-value并不会有任何问题,但是一个key只能关联一个value。在上面的代码中,一开始我们把key对象"apple"映射到Integer对象123,然后再次调用put()方法把"apple"映射到789,这时,原来关联的value对象123就被“冲掉”了。实际上,put()方法的签名是V put(K key, V value),如果放入的key已经存在,put()方法会返回被删除的旧的value,否则,返回null。

要正确使用HashMap,作为key的类必须正确覆写equals()hashCode()方法;
一个类如果覆写了equals(),就必须覆写hashCode(),并且覆写规则是:

  • equals()返回true,则hashCode()返回值必须相等;
  • 如果equals()返回false,则hashCode()返回值尽量不要相等。
  • 实现hashCode()方法可以通过Objects.hashCode()辅助方法实现。

其他数据结构

EnumMap

如果作为key的对象是enum类型,那么,还可以使用Java集合库提供的一种EnumMap,它在内部以一个非常紧凑的数组存储value,并且根据enum类型的key直接定位到内部数组的索引,并不需要计算hashCode(),不但效率最高,而且没有额外的空间浪费。

示例代码:

import java.time.DayOfWeek;
import java.util.EnumMap;
import java.util.Map;

public class AAA {
    public static void main(String[] args) {
        Map<DayOfWeek, String> map = new EnumMap<>(DayOfWeek.class);
        map.put(DayOfWeek.MONDAY, "星期一");
        map.put(DayOfWeek.TUESDAY, "星期二");
        map.put(DayOfWeek.WEDNESDAY, "星期三");
        map.put(DayOfWeek.THURSDAY, "星期四");
        map.put(DayOfWeek.FRIDAY, "星期五");
        map.put(DayOfWeek.SATURDAY, "星期六");
        map.put(DayOfWeek.SUNDAY, "星期日");
        System.out.println(map);
        System.out.println(map.get(DayOfWeek.MONDAY));
    }
}

小结:

  • 如果Mapkeyenum类型,推荐使用EnumMap,既保证速度,也不浪费空间。
  • 使用EnumMap的时候,根据面向抽象编程的原则,应持有Map接口。

TreeMap

SortedMap在遍历时严格按照Key的顺序遍历,最常用的实现类是TreeMap;

  • 作为SortedMap的Key必须实现Comparable接口,或者传入Comparator
  • 要严格按照compare()规范实现比较逻辑,否则,TreeMap将不能正常工作。
    示例代码:
import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;

public class AAA {
    public static void main(String[] args) {
        Map<Student, Integer> map = new TreeMap<>(new Comparator<Student>() {
            public int compare(Student p1, Student p2) {
                if (p1.score == p2.score) {
                    return 0;
                }
                return p1.score > p2.score ? -1 : 1;
            }
        });
        map.put(new Student("Tom", 77), 1);
        map.put(new Student("Bob", 66), 2);
        map.put(new Student("Lily", 99), 3);
        for (Student key : map.keySet()) {
            System.out.println(key);
        }
        System.out.println(map.get(new Student("Bob", 66))); // null?
    }
}

class Student {
    public String name;
    public int score;
    Student(String name, int score) {
        this.name = name;
        this.score = score;
    }
    public String toString() {
        return String.format("{%s: score=%d}", name, score);
    }
}

思考题

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-07-28 13:23:41  更:2021-07-28 13:23:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/9 4:57:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码