【Java基础知识7】集合

一、什么是集合?

在Java中,集合(Collection)指的是一组数据容器,它可以存储多个对象,并且允许用户通过一些方法来访问与操作这些对象。Java提供了一系列接口和类来支持不同类型的集合。 Collection接口,主要用于存放单一元素; Map 接口,主要用于存放键值对。

二、Java集合和数组的区别?

数组不是面向对象的,存在明显的缺陷,集合弥补了数组的缺点,比数组更灵活更实用,而且不同的集合框架类可适用不同场合。

  • 数组存放基本数据类型和对象,而集合类存放的都是对象,集合类不能存放基本数据类型。数组和集合存放的对象皆为对象的引用地址;
  • 数组容易固定无法动态改变,集合类容量动态改变;
  • 数组无法判断其中实际存有多少元素,length只告诉了数组的容量,而集合的size()可以确切知道元素的个数;
  • 集合有多种实现方式和不同适用场合,数组仅采用顺序表方式
  • 集合以类的形式存在,具有封装、继承、多态等类的特性,通过简单的方法和属性即可实现各种复杂操作,大大提高了软件的开发效率。

三、Java集合框架

四、List

继承自Collection,是一个有序的集合,可以包含重复元素。

实现类:

  • ArrayList:数组实现,查询快,增删慢,轻量级;(线程不安全)
  • LinkedList:双向链表实现,增删快,查询慢 (线程不安全)
  • Vector:数组实现,重量级 (线程安全、使用少)

ArrayList和LinkedList区别

ArrayList是基于动态数组实现的,而LinkedList是基于双向链表实现的。它们都实现了List接口。

ArrayListLinkedList
获取指定元素速度很快需要从头开始查找元素
添加元素到末尾速度很快速度很快
在指定位置添加/删除需要移动元素不需要移动元素
内存占用较大

ArrayList适合随机访问,而LinkedList适合插入和删除操作。在选择列表实现时,需要根据实际的用例来决定。如果应用场景中包含大量的插入和删除操作,LinkedList可能是更好的选择。相反,如果需要频繁地随机访问元素,ArrayList将提供更好的性能。

List特点

List接口允许我们添加重复的元素,即List内部的元素可以重复:

public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("apple"); // size=1
        list.add("pear"); // size=2
        list.add("apple"); // 允许重复添加元素,size=3
        System.out.println(list.size());
    }

List还允许添加null

public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("apple"); // size=1
        list.add(null); // size=2
        list.add("pear"); // size=3
        String second = list.get(1); // null
        System.out.println(second);
    }

List遍历方法

// 索引
public static void main(String[] args) {
        List<String> list = List.of("apple", "pear", "banana");
        for (int i=0; i<list.size(); i++) {
            String s = list.get(i);
            System.out.println(s);
        }
    }

//迭代器Iterator
public static void main(String[] args) {
        List<String> list = List.of("apple", "pear", "banana");
        for (Iterator<String> it = list.iterator(); it.hasNext(); ) {
            String s = it.next();
            System.out.println(s);
        }
    }

//foreach
public static void main(String[] args) {
        List<String> list = List.of("apple", "pear", "banana");
        for (String s : list) {
            System.out.println(s);
        }
    }

List转Array

public static void main(String[] args) {
        List<String> list = List.of("apple", "pear", "banana");
        Object[] array = list.toArray();
        for (Object s : array) {
            System.out.println(s);
        }
    }

public static void main(String[] args) {
        List<Integer> list = List.of(12, 34, 56);
        Integer[] array = list.toArray(new Integer[3]);
        for (Integer n : array) {
            System.out.println(n);
        }
    }

Array转List

Integer[] array = { 1, 2, 3 };
List<Integer> list = List.of(array);

五、Set

继承自Collection,是一个无序集合,不允许存放重复的元素;允许使用null元素。

HashSet

  • 基于哈希表实现,不保证元素的顺序,不是线程安全的,存取速度比较快,不允许保存重复元素(可以实现去重操作);
  • 底层是HashMap,放到HashSet集合中的元素等同于放到HashMap集合key部分了;

  • HashSet 按 Hash 算法来存储集合中的元素,因此具有很好的存取、查找、删除性能

HashSet添加元素过程

  1. 首先判断hashCode()值是否相同
  2. ->继续执行equals(),看其返回值
  3. ->是true:说明元素重复,不添加 是false:就直接添加到集合
  4. ->否:就直接添加到集合
  5. 最终自动生成hashCode()和equals()

LinkedHashSet

也是基于哈希表,但它维护了一个链表来保证插入顺序。

TreeSet

  • 有序,唯一,不重复 ,不允许为null主要用作排序,自然排序和定制排序,默认情况下,TreeSet 采用自然排序;
  • 底层是TreeMap,放到TreeSet集合中的元素等同于放到TreeMap集合key部分了,红黑树(自平衡的排序二叉树);

  • TreeSet的有序存储,存储元素时会判断他是否重复,并且自动排序,判断重复元素由compareTo()方法来实现。因此自定义类要使用TreeSet必须覆写Comparable接口。具体的排序规则可以由我们自己来定

       ┌───┐
       │Set│
       └───┘
         ▲
    ┌────┴─────┐
    │          │
┌───────┐ ┌─────────┐
│HashSet│ │SortedSet│
└───────┘ └─────────┘
               ▲
               │
          ┌─────────┐
          │ TreeSet │
          └─────────┘
// HashSet
Set<String> hashSet = new HashSet<>();
hashSet.add("Java");
hashSet.add("Kotlin");

// LinkedHashSet
Set<String> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add("Java");
linkedHashSet.add("Kotlin");

// TreeSet
Set<String> treeSet = new TreeSet<>();
treeSet.add("Java");
treeSet.add("Kotlin");

六、Map

提供了一组键值对的映射。其中存储的每个对象都有一个相应的关键字(key),关键字决定了对象在Map中的存储位置。关键字应该是唯一的,每个key 只能映射一个value。

实现类数据结构是否线程安全key能否为null是否有序
HashMap数组+链表+红黑树
LinkedHashMap数组+链表+红黑树+双重链接列表
Hashtable数组+链表
TreeMap红黑树

HashMap

HashMap是 Map 接口使用频率最高的实现类。

  • 允许使用null键和null值,与HashSet一样,不保证映射的顺序。
  • 所有的key构成的集合是Set:无序的、不可重复的。所以,key所在的类要重写:equals()和hashCode()
  • 所有的value构成的集合是Collection:无序的、可以重复的。所以,value所在的类要重写:equals()
    一个key-value构成一个entry
  • 所有的entry构成的集合是Set:无序的、不可重复的
    HashMap 判断两个 key 相等的标准是:两个 key 通过 equals() 方法返回 true,hashCode 值也相等。
    HashMap 判断两个 value相等的标准是:两个 value 通过 equals() 方法返回 true。

注:

JDK 7及以前版本:HashMap是数组+链表结构(即为链地址法)
JDK 8版本发布以后:HashMap是数组+链表+红黑树实现。

LinkedHashMap

LinkedHashMap继承了HashMap,是Map接口的哈希表和链接列表实现,它维护着一个双重链接列表,此链接列表定义了迭代顺序,该迭代顺序可以是插入顺序或者是访问顺序。

Hashtable

  • Hashtable是早期的字典实现类,可以方便的实现数据的查询
  • Hashtable和HashMap从存储结构和实现来讲有很多相似之处,不同的是它承自Dictionary类,而且是线程安全的,另外Hashtable不允许key和value为null,并发性不如ConcurrentHashMap。
  • Hashtable不建议在新代码中使用,不需要线程安全的场合可以用HashMap替换,需要线程安全的场合可以用ConcurrentHashMap替换。

Properties

  • Properties 类是 Hashtable 的子类,该对象用于处理属性文件
  • 由于属性文件里的 key、value 都是字符串类型,所以 Properties 里的 key 和 value 都是字符串类型
  • 存取数据时,建议使用setProperty(String key,String value)方法和getProperty(String key)方法

TreeMap

 Map集合的主要功能是依据key实现数据的查询需求,为了方便进行key排序操作提供了TreeMap集合,TreeMap实现SortMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序(自然顺序),也可以指定排序的比较器,当用Iterator遍历TreeMap时,得到的记录是排过序的。

ListSetMap各自适用于不同的场景,例如,当需要保持元素顺序时使用List,当需要唯一性时使用Set,而当需要存储键值对时使用Map

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农的日常生活c

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值