2021-7-21 Java课堂笔记Day11

1 List集合的实现类

1.1 ArrayList

ArrayList特点
  • 底层为数组结构,查询快,增删慢,本质上是一个长度可变(ArrayList对象的引用可变)的数组
  • 实现不同步
  • 进行扩容时会将容量变为原来的1.5倍

在1.8前后 ArrayList的实现区别

JDK1.7:创建时直接创建了一个长度为10的数组,类似于饿汉式

JDK1.8以后:创建时创建一个长度为0的数组,当添加元素时,再创建一个长度为10的数组,类似于懒汉式

1.2 LinkedList

底层为双向链表,增删快,查询慢

有头插法和尾插法两种方法添加元素

voidaddFirst(E e) 在该列表开头插入指定的元素。
voidaddLast(E e) 将指定的元素追加到此列表的末尾。
Eelement() 检索但不删除此列表的头(第一个元素)。
EgetFirst() 返回此列表中的第一个元素。
EgetLast() 返回此列表中的最后一个元素

1.3 Vector

是一个古老的集合(在JDK1中就有),底层是可变数组

Vector是同步的,如何不需要线程安全的实现,建议使用ArrayList代替Vector

1.4 List的实现类的选择

  • ArrayList 数据查找频率高时使用
  • LinkedList 数据元素操作频率高时使用
  • Vector 效率低于其他实现类,如果不考虑线程安全则不使用

面试题

ArrayList / LinkedList / Vector 的异同?ArrayList 的底层实现是什么?扩容机制?Vector 和ArrayList的区别?

ArrayList和LinkedList的异同

二者的线程都是不安全的,但相对于线程安全的 Vector 的效率高

ArrayList 是基于动态数组的数据结构,LinkedList 是基于链表的数据结构;对于元素的 get 和 set ,ArrayList(索引) 优于LinkedList(移动指针);对于新增、删除等操作 LinkedList(改变指针指向) 效率高于 ArrayList(移动数据)。

ArrayList 和 Vector 的区别

Vector 是线程安全且同步的而 ArrayList 不是

扩容机制: ArrayList 扩容是原来的1.5倍,Vector 扩容是原来的2倍

2 Set集合

  • 不包含重复元素
  • 最多只有一个 null 值
  • 没有索引,只能通过增强 for 循环和迭代器遍历
  • Set 集合无序(集合中的元素添加顺序和迭代顺序不一致)

2.1 Set 的实现类

2.1.1 HashSet

HashSet 特点:

  • 底层数据结构是哈希表
  • 对于迭代的顺序不做保证,即保存顺序和获取顺序不一致
  • 没有索引,只能通过增强 for 循环和迭代器遍历
  • 不包含重复元素
  • 最多只有一个 null 值
  • 此实现不同步
  • 初始容量为16 扩容时变为原来的1.75倍
2.1.2 HashSet 集合元素唯一性

原理:

  • 获取对象哈希码,根据哈希码计算存储位置

    • 当前位置没有元素——>直接存储
    • 当前位置有元素——>进行下一步
  • 将对象的哈希值和当前位置所有元素的哈希值比较

    • 哈希值不同——>直接存储
    • 哈希值相同——>进行下一步
  • 通过 equals 方法比较两个元素内容

    • 内容不同——>直接存储
    • 内容相同——>判断元素重复,不存储

对于存入hashSet集合中对象,都必须重写hashCode和equals方法 保证元素的唯一性

2.2 哈希表

数据结构中的一种

JDK8之前,哈希表底层采用数组+链表来实现,可以认为是一个元素为链表的数组

JDK8之后,哈希表底层采用数组+链表+红黑树来实现,当链表长度超过一定值时就会将其转换成红黑树

2.3 LinkedHashSet

特点:

  • 是 Set 接口的哈希表和双向链表的实现,是有序的
  • 唯一性

格式:

Set 对象名 = new LinkedHashSet()

2.4 TreeSet

  • 基于 TreeMap 实现
  • 可对其中元素进行排序,排序方式:自然排序、定制排序
  • 此实现不同步

格式:

TreeSet 对象名 = new TreeSet()

2.4.1 自然排序

对于存入 TreeSet 的数据都必须实现 Comparable 接口

Comparable 接口:

该接口会对实现他的每个类进行一个整体排序,称之为类的自然排序,其方法 compareTo 称之为自然比较方法

Comparable 方法

int compareTo(T o)(o 为要比较的对象)

将此对象与指定对象进行比较,返回值为负整数、零、正整数,代表该对象小于、等于、大于指定对象

通过实现Comparable 接口并且重写 compareTo()方法可以将想要的数据类型保存到 TreeSet 集合中,重写方法时要注意排序规则,并且最好主要条件和次要条件都有定义

2.4.2 定制排序(比较器排序)

Comparator 接口

Comparator方法

int compare(T o1,T o2)比较两个参数的顺序

在定制排序中需要用到 TreeSet 的构造方法 TreeSet(Comparator<? super E> comparator) 构造一个新的集合,根据指定的比较器进行排序

推荐使用匿名内部类,也可在新建一个类实现比较器的接口

格式:

TreeSet 对象名 = new TressSet(new Comparator(){匿名内部类主体});

3 泛型

是JDK1.5引入的特性,提供了编译时类型的安全检测机制,允许在编译时检测非定义类型的数据。本质是参数化类型,即由会操作的数据类型进行

参数类型理解:将类型原来的具体类型参数化,然后在使用/调用时传入具体的类型

(输入数据时类似形参,输出结果类似实参)

该参数化类型可用于类、方法和接口,分别称为泛型类、泛型方法、泛型接口

格式:

<类型> 指定一种类型

<类型1,类型2,……> 指定多种类型

泛型的好处:

  • 在编译时期就能检测数据类型
  • 避免强制类型转换

3.1 泛型的应用

public static void main(String[] args) {
        List<String>  list1 = new ArrayList<String>();//在jdk7以前
        List<String>  list2 = new ArrayList<>();//在jdk7开始    菱形语法
        list2.add("abc");
        list2.add("12");
    	list2.add(123);//报错
        for(String str : list2){
            System.out.println(str);
        }

3.2 自定义泛型

3.2.1 定义泛型类

格式:

修饰符 class 类名 T可为任意标识符 其余还有E K V 等

自定义泛型类中的 get 和 set 不是泛型方法

3.2.2 泛型方法

格式:

修饰符 返回类型 方法名称(参数列表)

3.2.3 泛型接口

格式:

修饰符 interface 接口名

3.2.4 泛型通配符

用于表示泛型 List 的父类,形式为<?>

List<?> 表示一个元素类型未知的 List,他的元素可以匹配任意类型,但不能往其中添加元素

通配符的基本用法:

类型通配符的上限:<?extends 类型> 表示的类型为该类型或该类型的子类

类型通配符的下限:<?super 类型> 表示的类型为该类型或该类型的父类

通配符用法:在要用集合做参数时,可用其接收一个知道 List 却不知道其泛型类型的集合作为实参

通配符好处:

  • 提高了代码的通用性和扩展性
  • 可以接受任意类型的集合作为实参

泛型擦除:泛型只在编译期有效,在运行时(如输出)泛型会丢失,该现象称为泛型擦除

4 可变参数

可用作方法的形参,作为形参时方法的参数可变

用法于数组相同

格式:

修饰符 返回值类型 方法名 (数据类型。。。变量名) 表面该方法可以接受指定数据类型的多个参数

注意事项:在一个方法中可有多个参数,但只能有一个可变参数,且可变参数必须在参数列表末尾

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值