什么是集合

集合是Java中存储对象数据的一种容器

集合有什么特点

  1. 大小不固定,类型也可以不固定(通常需要泛型约束)
  2. 集合只能存储引用数据类型
  3. 集合适合对容器中的元素进行增删操作

体系结构



Java里column函数的用法 java中column什么意思_Powered by 金山文档


Collection单列集合,每个元素(数据)只包含一个值。

Map双列集合,每个元素包含两个值(键值对)。

4. Collection

什么是Collection

官方的解释:

  • Collection是集合层次结构中的根接口。 集合表示一组对象,称为其元素 。 有些集合允许重复元素而其他集合则不允许。 有些是有序的,有些是无序的。
  • JDK不提供此接口(Collection)的任何直接实现:它提供了更具体的子接口的实现,如 Set 和 List
  • 此接口通常用于传递集合并在需要最大通用性的情况下对其进行操作。

说的通俗一点就是:

  • Collection是根接口,所有集合都来自Collection
  • jdk不提供该接口实现类对象,但提供了更具体的实现类
  • 就好比父类和子类,你可以用父类对象接收一个子类的实例化对象

例如:Father f = new Sun(); // Sun类继承了Father类

Collection的体系结构


Java里column函数的用法 java中column什么意思_Java里column函数的用法_02


常用方法

方法名称

说明

public boolean

把给定的对象添加到当前集合中

public void

清空集合中所有的元素

public boolean

把给定的对象在当前集合中出现的第一个位置删除,如果删除失败返回false

public boolean

判断当前集合中是否包含给定的对象

public boolean

判断当前集合是否为空

public int

返回集合中元素的个数。

public Object[]

把集合中的元素,存储到数组中


集合的遍历方式

迭代器

Iterator是集合专用的迭代方法,只能集合调用

Iterator中常用方法

  • next():返回迭代中的下一个元素
  • hasNext():如果迭代具有更多元素,则返回true
Collection<Integer> list = new ArrayList<>();
Iterator<Integer> iterator = list.iterator();
while(iterator.hasNext()){
    Integer next = iterator.next();
    System.out.println(next);
}

注意事项:

  1. 迭代器只能使用一次
  2. next()移动指针到下一个元素,如果没有抛异常
  3. hasNext()检查下一个元素是否为空,但不移动指针
  4. 迭代器迭代元素越界出现:NoSuchElementException

普通for

只适用于List系列集合,因为他有序

通过调用集合的get方法,根据索引取值

增强for

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(3);
list.add(2);
//增强for
for (int i : list) {
    if (i == 3) {
        i = 5;//增强for中如果对取出的这个元素修改,将不会对集合产生影响
    }
    System.out.println(i);
}

Lambda迭代

// 使用lambda表达式集合的迭代 
colStr.forEach(new Consumer() { 
    @Override public void accept(String s) { 
        System.out.println(s); 
    } 
}); 
// 简化写法 
System.out.println("-------------------------"); 
colStr.forEach(s-> System.out.println(s)); 
System.out.println("-------------------------"); 
// 再次简化 
colStr.forEach(System.out::println);

5.List

Collection的子接口

特点

有序,有索引(是独有的),可重复,可存储null值,此实现不同步,线程不安全

存储和取出顺序一致

常用方法(特有)

方法名称

说明

注意

void

将给定的元素插入到指定位置

索引不能越界,否则报错


E

返回该索引位置的元素,没找到返回-1

E

对给定位置的元素进行替换

E

删除指定位置的元素

int

返回特定元素在集合中最后一次出现的位置

没找到返回-1

int

返回特定元素在集合中第一次出现的位置

ListIterator<E>

List集合特有的迭代器


List<E>

根据开始索引和结束索引(左闭右开)返回一个新的集合,该集合是原集合的子集



ListIterator叫做列表迭代器,将在第3.2解释

迭代方式

和Collection一样的:迭代器、增强for(不能直接使用普通for需要转换为数组)、Lambda表达式

List独有的:listIterator、普通for(因为有索引)

并发修改异常(忘记老师说的了,可能面试会问)

迭代器在迭代集合,但是集合本身被修改,换而言之:就是在同一时刻只能有一个对象来操作集合

下面两种情况会出现并发修改异常
  1. 迭代器和集合方法都会对集合进行操作
while(stringListIterator.hasNext()){ 
    String ele = stringListIterator.next(); 
    if("css".equals(ele)){ 
        stringListIterator.remove();//允许 
        //list.remove("css");// 不允许 出现 ConcurrentModificationException 
    } 
    System.out.println(ele); 
}
  1. 增强for本身也是一个Iterator迭代器,同样不能使用
for (String s : list) {
    if("2".equals(s)){
        list.remove("2");//不允许,并发修改异常
    }
    System.out.println(s);
}

这种情况不会

for (int i= 0; i < list.size();i++){ 
    String ele = list.get(i); 
    if("css".equals(ele)){ 
        list.remove("css");// 允许 
    } 
} 
System.out.println(list);

总结

  1. 同一时间只能有一个对象操作集合
  2. 使用迭代器要保证集合不在改变
  3. 出现异常的原因:
  4. 迭代器在进行遍历过程中,如果对数组进行操作,会导致迭代器的实际修改值和集合的预期修改值不对应,就会出异常
  5. 迭代器是一次性的,如果对集合进行操作,没有及时更新迭代器就会引发异常
  6. 如何解决并发修改异常
  7. 使用普通for:用索引取值,同一时间只有一个对象对集合操作
  8. 使用列表迭代器ListIterator

ListIterator

  1. ListIterator的两个遍历方法

boolean

hasNext()

从前往后遍历

boolean

hasPrevious()

从后往前遍历,前提是先得从前往后遍历一遍,让迭代器指针走到末尾


List<String> list = new ArrayList<>();
ListIterator<String> listIterator = list.listIterator();
  1. ListIterator和Iterator的区别
  2. 每进行一次迭代都会把实际修改值重新赋值给预期修改值,但是Iterator不行
  3. ListIterator是List集合特有的,Iterator是所有集合都有的

两个主要的接口实现类

特点

List的接口实现类,List的特点就是ArrayList、LinkedList的特点

ArrayList

  • 使用的是数组,默认容量为10
  • 一旦数组满了,则创建一个新的数组,新数组的容量是原数组的容量的1.5倍。并且会将原数组内容复制到新数组
  • 因为底层是数组,具有数组的特点:查询快,增删慢


Java里column函数的用法 java中column什么意思_迭代器_03


  • 可存储null值
  • 此实现不同步,线程不安全

LinkedList

  • 底层是双向链表
  • 具有链表的特点:查询慢,增删快
  • 此实现不同步,线程不安全
  • 常用方法


Java里column函数的用法 java中column什么意思_迭代器_04


Java里column函数的用法 java中column什么意思_java_05


Java里column函数的用法 java中column什么意思_Java里column函数的用法_06


6.Set

特点

元素唯一,无序,没有索引,最多只能一个null

三个主要的接口实现类

HashSet、TreeSet、LinkedHashSet

HashSet

特点:无序(HashSet只是不保证有序,并不是保证无序),不重复,无索引,此实现不同步(暂时不了解)

底层实现:哈希表,是一种对增删改查性能都较好的结构

哈希表组成

jdk8之前:数组+链表

jdk8之后:数组+链表+红黑树

哈希值
  • 哈希值是jdk根据对象计算得出的内存地址,根据某个规则算出来的int类型数值
  • 对象可以通过调用hashCode()返回对象的哈希值
  • 同一个对象的哈希值是相同的
  • 在默认情况下,不同对象的哈希值是相同的(除非重写了hashCode方法)

HashSet底层存储结构

  1. 当调用无参hashSet构造器,会默认创建一个长度为16的数组
  2. 添加元素,元素哈希值和数组长度根据哈希算法计算元素存储位置
  3. 判断该位置是否为空,如果为空直接存数组
  4. 如果位置不为空,判断哈希值,如果不同直接存链表
  5. 如果哈希值相同,判断equals是否相同,如果不同直接存链表
  6. 如果都相同就不存
版本差异

jdk8之前:新元素占据旧元素位置,指向旧元素。当元素链表挂载元素过多会造成查询性能下降。

jdk8之后:新元素挂在旧元素下面。当链表长度超过8时,自动将链表转换为红黑树,进一步提高性能

元素去重原理(面试会问)
  1. 判断hashcode值是否相同,如果不同,则不重复
  2. 如果hashcode相同,调用equals比较,如果为true,则重复。否则挂在元素下边
  3. 在类中可以重写equals和hashCode方法,进行自定义特征比较
@Override 
public boolean equals(Object o) { 
    if (this == o) 
        return true; 
    if (o == null || getClass() != o.getClass()) 
        return false; 
    Student student = (Student) o; 
    return Objects.equals(name, student.name); //例如这里
    //可以自定义比较对象中的哪一个特征,比如就比较名字是否一样,不在乎年龄是否一样
} 
@Override 
public int hashCode() { 
    return Objects.hash(name); //例如这里
    //可以自定义要进行计算哈希的对象,比如只想判断名字哈希是否一样,
    //名字哈希一样就认为这俩对象哈希一样,不在乎年龄哈希是否一样
}

TreeSet

特点:默认自然升序排序,不重复,无索引,可排序

排序方式

自然排序
  1. 必须实现Comparable接口,重写compareTo,定义排序规则
  2. Integer、String这些类默认已经实现了Comparable接口,可以直接去调用
  3. 英文按照字母顺序,中文按照Unicode码大小升序
比较器排序(定制排序):

创建集合时候就实现Comparator接口

如何理解排序呢

首先要知道这俩的区别

  • Comparable是比较接口,Comparator是比较器
  • 实现比较接口(Comparable)就意味着该类支持排序
  • 实现比较器(Comparator)就意味着该集合要使用自定义的比较方法
  • Comparable相当于“内部比较器”,而Comparator相当于“外部比较器”。

LinkedHashSet

  1. 特点:有序(存入和取出顺序一样),不重复,无索引
  2. 底层存储结构:哈希表和双向链表(记录存储的顺序)

7.集合工具类Collections

Collections 不属于集合,是用来操作集合的工具类


Java里column函数的用法 java中column什么意思_迭代器_07