栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java基础集合

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java基础集合

(一)

Collection

(二)

Map

  1. 集合主要是两组(单列集合,双列集合)
  2. Collection 接口有两个重要的子接口 List Set,他们都是单列集合
  3. Map接口的实现子类 是双列集合,存放的K-V

Collection:单列集合

List:有序,元素可以重复

ArrayList:用数组实现,有序,查找快(按索引查找),增删慢(牵扯到数组的增容问题);

linkedList:链表数据结构实现,有序,查找慢(查找时需要遍历),增删快;

Vector:原理跟ArrayList相同,只是他增加了线程安全,效率略低;

Set:无序,元素不可重复

HashSet:线程不安全,存取速度快,底层以哈希表实现;

TreeSet:红黑树的数据结构,默认对数据进行自然排序。比较两个对象返回的值为0的时候,元素重复;

Map:键值对,键不可重复,值可重复

HashMap:线程不安全(不支持同步),存取速度快,底层以哈希表实现,HashMap则允许有一个键值为null和多个value为null

TreeMap:红黑树的数据结构,默认对数据进行自然排序。比较两个对象返回的值为0的时候,元素重复;

HashTable:同步,不允许null做键值和value,

数组数据结构

特点:

查询和修改快

增加和删除满

ArrayList和Vector的底层是使用数组的数据结构

在ArrayList中初始化的长度是10,如果长度不够用了,每次会增加之前长度的50%,然后将旧的集合中的数据拷贝到新的集合中。Vector每次扩容的长度是之前的一倍

为什么查询和修改快?
查询和修改时直接通过数组的下标就能快速定位到相应的位置。
为什么增加和删除慢?
数组里面内存地址是连续的,如果要做增加或者删除时势必要修改长度,这样可能会导致牵一发而动全身的操作,比如在下标是2位置上的元素进行删除,那么后面每个位置上面的元素都会向前移动。

链表数据结构

特点:
增加和删除快
查询和修改慢

为什么增加和删除快?
链表里面的内存地址不是连续的,每个元素里面都保留着上一个元素和下一个元素的内存地址(首尾除外),如果要增加或删除元素时,只有与他相邻的两个位置上的元素发生变化,其他元素不用任何改变。
为什么查询和修改慢?
链表里面的内存地址不是连续的,要查找的话,需要从头或者尾部挨个查找,不能直接定位。

区别和共同点:

  • Vector和ArrayList的区别

Vector是线程安全的,效率低

ArrayList是线程不安全的,效率高

共同点:都是数组实现的

  • ArrayList和linkedList的区别

ArrayList底层是数组结构,查询和修改快

linkedList底层是链表结构的,增删比较快,查询和修改比较慢

共同点:都是线程不安全的

在开发中使用哪个?

查询多用ArrayList

增删多用linkedList

如果都多用ArrayList

Vector基本不用了,效率比较低

ArrayList线程安全的方案

如果使用ArrayList去替代Vector的话,需要考虑线程安全的问题,有两种方案

  • 可以使用Collections工具类中的synchronizedList方法可以将ArrayList变成线程安全的

    List list = Collections.synchronizedList(new ArrayList());
    
  • 使用java.util.concurrent包下面的CopyOnWriteArrayList,使用方式跟ArrayList一样

泛型的概念

通过API可以看到Collection,List,ArrayList,这几个类里面都有,有些类里面你看到的是或其他字母,这个就是泛型,泛型这个词我的理解是广泛的类型,其英文是Generic,可以直白的翻译为通用类型,尖括号里面的E可以是任何引用数据类型,也就是说这个E是不确定的,只有当你使用泛型指明了具体的数据类型之后,集合里面只能存储这种类型的数据了。试想下,向一个集合中存放多个不同类型的数据,在获取的时候是多么痛苦。

泛型的优点

  • 可以统一集合中的数据类型,提高安全性
  • 可以减少强制类型转换

不使用泛型时,我们可以向集合中添加任意类型的数据,但是在获取的时候要进行多次类型强制转换

泛型通配符

在实际工作当中,有可能通过调用某个方法来接受一个返回值List的数据,这样就不太好确定返回值中的数据类型,此时可以使用泛型通配符来解决,比如一个方法要根据传入的参数决定返回ArrayList还是ArrayList,下面返回值List中的?表示通配符

使用泛型通配符限定子类或者父类

List
向下限定,E及其子类,可以存储当前类型的子类
List
向上限定,E及其父类,可以存储当前类型的父类

增强for循环

使用增强for循环可以简化数组和Collection集合的遍历

    for(元素数据类型 变量 : 数组或者Collection集合) {
        使用变量即可,该变量就是元素
    }
集合框架中的三种迭代方式删除数据
  • 普通for循环,可以删除,注意让索引做自减运算
  • 迭代器,可以删除,但是必须使用迭代器自身的remove方法,否则会出现并发修改异常
  • 增强for循环不能删除

建议删除时用迭代器

可变参数

在定义方法的时候不确定该定义多少个参数时,可以使用可变参数来定义,这样方法的参数个数会根据调用者来确定。
注意:如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个。

修饰符 返回值类型 方法名(数据类型…  变量名){}

向HashSet中添加自定义类型

这里需要注意:在向HashSet中存放自定义类型对象时,一定要重写hashCode和equals方法

HashCode方法的作用

在HashSet中的元素是不能重复的,jvm可以通过equals方法来判断两个对象是否相同,假设自定义一个Person类里面有10个成员变量,每调用一次equals方法需要做10次if判断分别比较这10个成员变量是否相等,如果想HashSet中存放100个对象,那就会做1000次if判断,数据量大的话会严重影响性能。
要解决这个问题的话可以这样做,将一些特征相似或相近的对象归类放到一起给他们一个编号,在做equals判断时,先比较这些编号,编号相同的话再去比较equals,这样可以减少一些比较次数。这个编号可以通过HashCode方法获得。HashCode方法的作用就是将对象进行分类,然后获取到编号值。
举个例子,图书馆里面的书都是分好类的,想找《java编程思想》这本书,先找到计算机类的书架,然后再去找就行,倘若图书馆里面的书籍没有分类,那找起来就如大海捞针。

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + age;
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    return result;
}

为什么上面的prime的值是31?其实这个值改成别的也可以,只不过定义为31之后有一些好处:

  • 31是一个质数,质数是能被1和自己本身整除的数,并且这个数不大也不小
  • 31这个数好算,2的五次方-1,2向左移动5位

TreeSet

TreeSet的特点是可以对存放进去的元素进行排序。

compareTo方法的返回值

TreeSet使用了二叉树的数据结构,负数放到左边,正数放到右边。

  • 当compareTo方法返回0的时候,系统会认为两者一致,所以不会向集合中添加元素

  • 当compareTo方法返回正数的时候,系统将元素存储到右边,所以集合存取顺序一致

  • 当compareTo方法返回负数的时候,系统将元素存储到左边,所以集合会倒序存储

map中的元素是以键-值的方式存在的,通过键可以获取到值,键是不可以重复的,跟地图比较像,通过一个坐标就可以找到具体的位置。

linkedHashMap的特点:存取顺序一致

TreeMap的特点:可以对存储的元素进行排序

HashMap和Hashtable的区别

Hashtable是JDK1.0版本出现的,是线程安全的,效率低,不可以存储null键和null值
HashMap是JDK1.2版本出现的,可以存储null键和null值

Collctions工具类

有点类似于数组中的Arrays

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/424705.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号