Java的第十二篇文章——JAVA集合(上)

简介: Java的第十二篇文章——JAVA集合

第十二章 集合

学习目标

  • 认识集合框架
  • List集合的结构
  • ArrayList集合使用
  • ArrayList源码解析
  • LinkedList集合使用
  • LinkedList源码解析
  • 对象的哈希值
  • 哈希表数据结构
  • Collections工具类
  • 了解泛型及其定义
  • 哈希表确定对象唯一性
  • HashSet源码解析
  • 红黑树结构Red/Black Tree Visualization
  • 对象的自然顺序与比较器

 

1. 集合框架的由来

JDK1.2版本后,出现这个集合框架,到JDK1.5后,大幅度优化。

  • 集合本质上是存储对象的容器
  • 数组也能存储对象,数组弊端就是定长
  • 解决数组的问题,开发出来集合框架,集合框架无需考虑长度
  • 集合和数组的区别与共同点
  • 集合,数组都是容器,都可以存储数据
  • 集合只存储引用数据类型,不存储基本数据类型(如int,就会换成包装类Integer)
  • 数组可以存储基本类型,也可以存储引用类型
  • 数组定长,集合容器变长

牢记:数据多了存数组,对象多了存集合

  • 集合学习的关键点
  • 怎么存储数据
  • 怎么取出数据
  • 选择哪种容器

 

2. 集合框架的继承体系

 

3. Collection接口

是所有单列集合的顶级接口,任何单列集合都是他的子接口,或者是实现类,该接口中定义的方法,是所有单列集合的共性方法。

Collection<E> 尖括号就是泛型,E我们要写,集合存储的数据类型

3.1 Collection接口的常用方法

方法的定义 方法作用
boolean add(E) 元素添加到集合
void clear() 清空集合容器中的元素
boolean contains(E) 判断元素是否在集合中
boolean isEmpty() 判断集合的长度是不是0,是0返回true
int size() 返回集合的长度,集合中元素的个数
boolean remove(E) 移除集合中指定的元素,移除成功返回true
T[] toArray(T[] a) 集合转成数组

(1) boolean add(E)

/**
*  boolean add(E) 元素添加到集合中
*  返回值,目前都是true
*/
public static void collectionAdd(){
    //接口多态创建集合容器对象,存储的数据类型是字符串
    Collection<String> coll = new ArrayList<>();
    //集合对象的方法add添加元素
    coll.add("hello");
    coll.add("world");
    coll.add("java");
    coll.add("money");
    coll.add("wife");
    /**
    *  输出语句中,输出集合对象,调用的是方法toString()
    *  看到的内容是一个完整的字符串, 不叫遍历
    *  遍历时一个个过,一个个输出
    */
    System.out.println(coll);
}

(2)void clear(),int size(),boolean isEmpty()

/**
     *  void clear() 清空集合中的所有元素
     *  int size() 集合的长度
     */
    public static void collectionClear(){
        Collection<Integer> coll = new ArrayList<>();
        coll.add(1);
        coll.add(2);
        coll.add(3);
        System.out.println(coll);
        System.out.println("集合的长度::"+ coll.size());//长度
        coll.clear();
        System.out.println(coll);
        System.out.println("集合的长度::"+ coll.size());
        System.out.println("集合是空吗?" + coll.isEmpty());//长度=0,isEmpty()返回true
    }

(3)boolean contains(),boolean remove()

/**
     *  boolean contains(E) 判断是否包含
     *  boolean remove(E) 移除元素
     */
public static void collectionContains(){
    //接口多态创建集合容器对象,存储的数据类型是字符串
    Collection<String> coll = new ArrayList<>();
    //集合对象的方法add添加元素
    coll.add("hello");
    coll.add("wife");
    coll.add("world");
    coll.add("java");
    coll.add("money");
    coll.add("wife");
    //判断集合中是否包含某个元素
    boolean b = coll.contains("world");
    System.out.println("b = " + b);
    //移除集合中的元素
    //删除成功返回true,如果有多个相同的对象,删除最先遇到的那个
    boolean b1 = coll.remove("wife");
    System.out.println("b1 = " + b1);
    System.out.println(coll);
}

 

4. Iterator接口

迭代器接口 Iterator,为集合进行遍历的。迭代器技术是所有Collection集合的通用遍历形式。

4.1 Iterator接口的抽象方法

  • boolean hasNext() 判断集合中是否有下一个可以遍历的元素,如果有返回true
  • E next() 获取集合中下一个元素
  • void remove() 移除遍历到的元素

4.2 获取迭代器接口实现类

迭代器就是为了遍历集合而产生。集合的顶层接口Collection中定义了方法:方法的名字就是 iterator(),返回值是Iterator接口类型, 返回的是Iterator接口实现类的对象

Collection接口中的方法摘要 :
  public Iterator iterator() ; 返回迭代器接口实现类的对象
使用的对象ArrayList,实现接口Collection,重写方法iterator();
public static void main(String[] args) {
    //迭代器遍历集合
    //接口多态创建集合容器对象,存储的数据类型是字符串
    Collection<String> coll = new ArrayList<>();
    //集合对象的方法add添加元素
    coll.add("hello");
    coll.add("world");
    coll.add("java");
    coll.add("money");
    coll.add("wife");
    //1 遍历 集合对象,调用方法iterator() 获取迭代器接口的实现类对象
    Iterator<String> it = coll.iterator();
    //2 迭代器对象的方法,判断集合是否有下元素
    //boolean b = it.hasNext();
    //System.out.println(b);
    //3 迭代器对象的方法,取出元素
    //String str = it.next();
    //System.out.println(str);
    //条件,集合中有下一个元素就可以
    while ( it.hasNext() ){
        String str =  it.next();
        System.out.println(str);
    }
}

4.3 迭代器的实现原理

每个集合容器,内部结构不同,但是迭代器都可以进行统一的遍历实现

结论:迭代器是隐藏在集合的内部的(即为成员内部类),提供公共的访问方式。

//Iterator接口的源码和ArrayList中的iterator的源码
interface Iterator{
    boolean hasNext();
    E next();
    void remove();
}
public class ArrayList {
    public Iterator iterator(){
        return  new Itr();
    }
    private class Itr implements Iterator{
         boolean hasNext(); //重写
       E next(); //重写
         void remove(); //重写
    }
}

图1:ArrayList的内部类实现接口Iterator的源码图片

4.4 并发修改异常

如何不发生这个异常

异常的产生原因:在迭代器遍历集合的过程中,使用了集合的功能,改变了集合的长度造成。

public static void main(String[] args) {
    //迭代器遍历集合
    //接口多态创建集合容器对象,存储的数据类型是字符串
    Collection<String> coll = new ArrayList<>();
    //集合对象的方法add添加元素
    coll.add("hello");
    coll.add("world");
    coll.add("java");
    coll.add("money");
    coll.add("wife");
    //迭代器遍历集合
    Iterator<String> it = coll.iterator();
    while ( it.hasNext() ){
        String str = it.next();
        //判断,遍历到的集合元素是不是java
        if (str.equals("java")){
            //添加元素 出现并发修改异常
            coll.add("add");
        }
        System.out.println(str);
    }
}

4.5 集合存储自定义对象并迭代

public static void main(String[] args) {
    //创建集合,存储自定义的对象
    Collection<Person> coll = new ArrayList<>();
    //集合的方法add存储Person对象
    coll.add( new Person("张三",21) );
    coll.add( new Person("李四",22) );
    coll.add( new Person("王五",23) );
    //迭代器遍历集合
    Iterator<Person> iterator = coll.iterator();
    while (iterator.hasNext()){
        Person person = iterator.next();
        System.out.println(person);
        System.out.println(person.getName());
    }
}

/**
 *  定义私有成员
 *  get set方法
 *  无参数构造方法
 *
 *  满足以上的三个条件 ,这个类,换一个名字,叫JavaBean
 */
public class Person   {
    private String name;
    private int age;
    public Person(){}
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

 

5. List接口

List接口,继承Collection接口,是单列集合。

5.1 List接口的特点

  • 这个接口的集合都具有索引
  • 这个接口中的元素允许重复
  • 这个接口中的元素是有序
  • 元素不会排序 ,有序指的是 ,元素存储和取出的顺序是一致的

List接口的所有实现类,都具有以上三个特征

5.2 List接口自己的方法(带有索引)

(1)void add(int index ,E e);

/**
* List接口的方法 add(int index, E e)
* 指定的索引位置,添加元素
*
*   IndexOutOfBoundsException 集合越界异常  长度是size()
*     StringIndexOutOfBoundsException 字符串越界异常  长度是 length()
*     ArrayIndexOutOfBoundsException 数组越界异常  长度是 length
*/
public static void listAdd(){
    List<String> list = new ArrayList<>();
    list.add("a") ;//集合的尾部添加
    list.add("b");
    list.add("c");
    list.add("d");
    list.add("e");
    System.out.println(list);
    //指定的索引上,添加元素 ,3索引添加元素
    list.add(3,"QQ");
    System.out.println(list);
}

(2)E get(int index);

/**
     *  List接口的方法 E get(int index)
     *  返回指定索引上的元素
     *  List集合可以使用for循环像数组一样的方式遍历
     */
    public static void listGet(){
        List<String> list = new ArrayList<>();
        list.add("a") ;//集合的尾部添加
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("e");
        //List接口方法get取出元素
        //String s = list.get(3);
        //System.out.println(s);
        for(int i = 0 ; i < list.size() ; i++){
            System.out.println(list.get(i));
        }
    }

(3)E set(int index,E e); E remove(int index);

/**
     * List接口方法
     *  E set (int index , E e) 修改指定索引上的元素,返回被修改之前的元素
     *  E remove(int index) 移除指定索引上的元素, 返回被移除之前的元素
     */
    public static void listSetRemove(){
        List<String> list = new ArrayList<>();
        list.add("a") ;//集合的尾部添加
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("e");
        System.out.println(list);
        //修改指定索引上的元素,3索引
        String str = list.set(3,"https://www.baidu.com");
        System.out.println(list);
        System.out.println(str);
        //删除指定索引上的元素,删除3索引
        str = list.remove(3);
        System.out.println(list);
        System.out.println(str);
    }

5.3 List集合的特有迭代器

List接口中的方法 listIterator() 返回迭代器,迭代器的接口是ListIterator,List集合的专用迭代器。

  • ListIterator迭代器接口的方法
  • boolean hasNext()
  • E next()
  • boolean hasPrevious() 判断集合中是否有上一个元素,反向遍历
  • E previous() 取出集合的上一个元素
/**
     * List接口的方法:
     *   listIterator() List集合的特有迭代器
     *   反向遍历
     */
    public static void iterator(){
        List<String> list = new ArrayList<>();
        list.add("a") ;//集合的尾部添加
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("e");
        //获取特有迭代器接口实现类对象
        ListIterator<String> lit = list.listIterator();
        //先要正向遍历
        while (lit.hasNext()){
            String s = lit.next();
            System.out.println(s);
        }
        System.out.println("=============");
        //判断上一个元素
        while (lit.hasPrevious()){
            //取出元素
            String s = lit.previous();
            System.out.println(s);
        }
    }

5.4 List接口的实现类的数据结构

LinkedList(链表)

  • 数组 :
  • 有索引,数组中元素的地址是连续,查询速度快
  • 数组的长度为固定,新数组创建,数组元素的复制,增删的效率慢
  • 链表
  • 链表没有索引,采用对象之间内存地址记录的方式存储
  • 查询元素,必须通过第一个节点依次查询,查询性能慢
  • 增删元素,不会改变原有链表的结构,速度比较快

 

6. ArrayList实现类

6.1 ArrayList集合的特点

ArrayList类实现接口ListArrayList具备了List接口的特性 (有序,重复,索引)

  • ArrayList集合底层的实现原理是数组,大小可变 (存储对象的时候长度无需考虑)。
  • 数组的特点:查询速度快,增删慢。
  • 数组的默认长度是10个,每次的扩容是原来长度的1.5倍。
  • ArrayList是线程不安全的集合,运行速度快。

6.2 ArrayList源码解析

6.2.1 ArrayList类的成员变量

private static final int DEFAULT_CAPACITY = 10; //默认容量
private static final Object[] EMPTY_ELEMENTDATA = {};//空数组
transient Object[] elementData; //ArrayList集合中的核心数组
private int size; //记录数组中存储个数
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; //数组扩容的最大值

6.2.2 ArrayList集合类的构造方法

//无参数构造方法
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //数组没有长度
//有参数的构造方法
public ArrayList(int 10) {
    if (initialCapacity > 0) {
        //创建了10个长度的数组
      this.elementData = new Object[10];
    } else if (initialCapacity == 0) {
      this.elementData = EMPTY_ELEMENTDATA;
    } else {
      throw new IllegalArgumentException("Illegal Capacity: "+
    initialCapacity);
    }
}

6.2.3 ArrayList集合类的方法add()

new ArrayList<>().add("abc"); //集合中添加元素
public boolean add("abc") {
    //检查容量  (1)
    ensureCapacityInternal(size + 1); 
    //abc存储到数组中,存储数组0索引,size计数器++
    elementData[size++] = "abc";//数组扩容为10
    return true;
}
//检查集合中数组的容量, 参数是1
private void ensureCapacityInternal(int minCapacity = 1) {
    //calculateCapacity 计算容量,方法的参是数组 , 1
    // ensureExplicitCapacity (10) 扩容的
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
//计算容量方法, 返回10
private static int calculateCapacity(Object[] elementData, int minCapacity = 1) {
    //存储元素的数组 == 默认的空的数组  构造方法中有赋值
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        //返回最大值   max(10,1)
      return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
}
//扩容 
private void ensureExplicitCapacity(int minCapacity = 10) {
    modCount++;
   // 10 - 数组的长度0 > 0
    if (minCapacity - elementData.length > 0)
        //grow方法(10) 数组增长的
      grow(minCapacity);
}
//增长的方法,参数是(10)
 private void grow(int minCapacity = 10) {
     //变量oldCapacity保存,原有数组的长度  = 0
     int oldCapacity = elementData.length; // 0
     //新的容量 = 老 + (老的 / 2)
     int newCapacity = oldCapacity + (oldCapacity >> 1);// 0
     // 0 - 10 < 0 新容量-计算出的容量
     if (newCapacity - minCapacity < 0)
      newCapacity = minCapacity; //新容量 = 10
     //判断是否超过最大容量
     if (newCapacity - MAX_ARRAY_SIZE > 0)
     newCapacity = hugeCapacity(minCapacity);
     // minCapacity is usually close to size, so this is a win:
//数组的赋值,原始数组,和新的容量
     elementData = Arrays.copyOf(elementData, newCapacity);
 }

 

7. LinkedList实现类

7.1 LinkedList集合的特点

LinkedList类实现接口List,LinkedList具备了List接口的特性 (有序,重复,索引)

  • LinkedList底层实现原理是链表,双向链表
  • LinkedList增删速度快
  • LinkedList查询慢
  • LinkedList是线程不安全的集合,运行速度快

7.2 LinkedList集合特有方法

集合是链表实现,可以单独操作链表的开头元素和结尾元素

  • void addFirst(E e) 元素插入到链表开头
  • void addLast(E e) 元素插入到链表结尾
  • E getFirst() 获取链表开头的元素
  • E getLast() 获取链表结尾的元素
  • E removeFirst() 移除链表开头的元素
  • E removeLast() 移除链表结尾的元素
  • void push(E e)元素推入堆栈中
  • E pop()元素从堆栈中弹出
public static void main(String[] args) {
  linkedPushPop();
}
//- void push(E e)元素推入堆栈中
//- E pop()元素从堆栈中弹出
public static void linkedPushPop(){
    LinkedList<String> linkedList = new LinkedList<String>();
    //元素推入堆栈中
    linkedList.push("a"); //本质就是addFirst() 开头添加
    linkedList.push("b");
    linkedList.push("c");
    System.out.println("linkedList = " + linkedList);
    String pop = linkedList.pop(); // removeFirst()移除开头
    System.out.println(pop);
    System.out.println("linkedList = " + linkedList);
}
//- E removeFirst() 移除链表开头的元素
//- E removeLast() 移除链表结尾的元素
public static void linkedRemove(){
    LinkedList<String> linkedList = new LinkedList<String>();
    linkedList.add("a"); //结尾添加
    linkedList.add("b"); //结尾添加
    linkedList.add("c"); //结尾添加
    linkedList.add("d"); //结尾添加
    System.out.println("linkedList = " + linkedList);
    //移除开头元素,返回被移除之前
    String first = linkedList.removeFirst();
    //移除结尾元素,返回被移除之前的
    String last = linkedList.removeLast();
    System.out.println("first = " + first);
    System.out.println("last = " + last);
    System.out.println("linkedList = " + linkedList);
}
//- E getFirst() 获取链表开头的元素
//- E getLast() 获取链表结尾的元素
public static void linkedGet(){
    LinkedList<String> linkedList = new LinkedList<String>();
    linkedList.add("a"); //结尾添加
    linkedList.add("b"); //结尾添加
    linkedList.add("c"); //结尾添加
    linkedList.add("d"); //结尾添加
    System.out.println("linkedList = " + linkedList);
    //获取开头元素
    String first = linkedList.getFirst();
    //获取结尾元素
    String last = linkedList.getLast();
    System.out.println("first = " + first);
    System.out.println("last = " + last);
    System.out.println("linkedList = " + linkedList);
}
// void addFirst(E e) 元素插入到链表开头
// void addLast(E e) 元素插入到链表结尾
public static void linkedAdd(){
    LinkedList<String> linkedList = new LinkedList<String>();
    linkedList.add("a"); //结尾添加
    linkedList.add("b"); //结尾添加
    linkedList.add("c"); //结尾添加
    linkedList.add("d"); //结尾添加
    System.out.println("linkedList = " + linkedList);
    //结尾添加
    linkedList.addLast("f");
    linkedList.add("g");
    //开头添加
    linkedList.addFirst("e");
    System.out.println("linkedList = " + linkedList);
}

7.3 LinkedList源码解析

7.3.1 LinkedList集合的成员变量

transient int size = 0; //集合中存储元素个数计数器
transient Node<E> first; //第一个元素是谁
transient Node<E> last; //最后一个元素是谁

7.3.2 LinkedList集合的成员内部类Node(结点)

//链表中,每个结点对象
private static class Node<E> {
        E item; //我们存储的元素
        Node<E> next; // 下一个结点对象
        Node<E> prev; // 上一个结点对象
    //构造方法,创建对象,传递上一个,下一个,存储的元素
    Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
}

7.3.4 LinkedList集合的方法add()添加元素

//添加元素 e 存储元素 abc
//再次添加元素 e
void linkLast(E "abc") {
    //声明新的节点对象 = last
    final Node<E> l = last; // l = null  l "abc"节点
    //创建新的节点对象,三个参数, 最后一个对象,"abc", 上一个对象null
    final Node<E> newNode = new Node<>(l, e, null);
    //新节点赋值给最后一个节点
    last = newNode;
    if (l == null)
        //新存储的几点赋值给第一个节点
      first = newNode;
    else
      l.next = newNode;
    size++;
    modCount++;
}

7.3.5 LinkedList集合的方法get()获取元素

//集合的获取的方法
//index是索引, size 长度计数器
Node<E> node(int index) {
    //索引是否小于长度的一半,折半思想
    if (index < (size >> 1)) {
      Node<E> x = first;
      for (int i = 0; i < index; i++)
        x = x.next;
     return x;
    } else {
       Node<E> x = last;
      for (int i = size - 1; i > index; i--)
      x = x.prev;
      return x;
    }
}

 

8. Set接口

Set集合,是接口Set,继承Collection接口。Set集合不存储重复元素。

Set集合存储的数据是无序、不重复、无索引。

无序指的是存储和取出的顺序不一样,但是由于使用迭代器遍历,Set集合的输出会根据自然顺序输出,例如“a”自然排序在“b”之前,所以先输出“a”。

Set接口下的所有实现类,都会具有这个特性。

Set接口的方法,和父接口Collection中的方法完全一样。

8.1 Set集合存储和遍历

public static void main(String[] args) {
        //Set集合存储并迭代
        Set<String> set = new HashSet<String>();
        //存储元素方法 add
        set.add("b");
        set.add("a");
        set.add("c");
        set.add("d");
        set.add("d");
        System.out.println("set = " + set);
        Iterator<String> it = set.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }
    }

8.2 Set接口实现类HashSet类

  • HashSet集合类的特点 :
  • 实现Set接口,底层调用的是HashMap集合
  • HashSet的底层实现原理是哈希表
  • HashSet不保证迭代顺序,元素存储和取出的顺序不一定
  • 线程不安全,运行速度快

图二:创建HashSet其实就是创建HashMap

8.3 对象的哈希值

每个类继承Object类,Object类定义方法:

public native int hashCode(); // C++语言编写,不开源

方法使用没有区别:方法返回int类型的值,就称为哈希值

 

哈希值的结果不知道是怎么计算的,调用toString()方法的时候,返回的十六进制数和哈希值是一样的,@1b6d3586叫哈希值 (根本和内存地址是无关的)

public static void main(String[] args) {
    Person p = new Person();
    int code = p.hashCode();
    // int 变量 460141958 (是什么,无所谓, 数字就是对象的哈希值)
    System.out.println(code);
    // com.atguigu.hash.Person@1b6d3586
    System.out.println(p.toString());
 }

可以重写父类的hashCode()方法,再输出该哈希值或toString()方法

/**
     * 重写父类的方法
     * 返回int值
     */
    public int hashCode(){
        return 9527;
    }

相关文章
|
16天前
|
安全 Java 大数据
|
14天前
|
安全 Java 开发者
【JAVA】哪些集合类是线程安全的
【JAVA】哪些集合类是线程安全的
|
14天前
|
Java
【JAVA】怎么确保一个集合不能被修改
【JAVA】怎么确保一个集合不能被修改
|
1天前
|
存储 安全 Java
Java一分钟之-集合框架进阶:Set接口与HashSet
【5月更文挑战第10天】本文介绍了Java集合框架中的`Set`接口和`HashSet`类。`Set`接口继承自`Collection`,特征是不允许重复元素,顺序不确定。`HashSet`是`Set`的实现,基于哈希表,提供快速添加、删除和查找操作,但无序且非线程安全。文章讨论了`HashSet`的特性、常见问题(如元素比较规则、非唯一性和线程安全性)以及如何避免这些问题,并提供了代码示例展示基本操作和自定义对象的使用。理解这些概念和注意事项能提升代码效率和可维护性。
8 0
|
1天前
|
存储 安全 算法
Java一分钟之-Java集合框架入门:List接口与ArrayList
【5月更文挑战第10天】本文介绍了Java集合框架中的`List`接口和`ArrayList`实现类。`List`是有序集合,支持元素重复并能按索引访问。核心方法包括添加、删除、获取和设置元素。`ArrayList`基于动态数组,提供高效随机访问和自动扩容,但非线程安全。文章讨论了三个常见问题:索引越界、遍历时修改集合和并发修改,并给出避免策略。通过示例代码展示了基本操作和安全遍历删除。理解并正确使用`List`和`ArrayList`能提升程序效率和稳定性。
6 0
|
3天前
|
存储 安全 算法
掌握Java并发编程:Lock、Condition与并发集合
掌握Java并发编程:Lock、Condition与并发集合
11 0
|
3天前
|
存储 安全 Java
深入理解Java集合框架
深入理解Java集合框架
8 0
|
8天前
|
存储 安全 Java
Java集合的分类有哪些?
Java中的集合就像一个容器,专门用来存储Java对象,这些对象可以是任意的数据类型,并且长度可变。这些集合类都位于java.util包中,在使用时一定要注意导包的问题,否则会出现异常。
34 10
|
11天前
|
安全 Java
循环的时候去删除集合中的元素 java.util.ConcurrentModificationException
循环的时候去删除集合中的元素 java.util.ConcurrentModificationException
|
13天前
|
Java
【专栏】Java 8 的 Streams 提供了一种处理数据集合的新方式,增强了代码的可读性和可维护性
【4月更文挑战第28天】Java 8 的 Streams 提供了一种处理数据集合的新方式,增强了代码的可读性和可维护性。本文介绍了 Streams 的基本概念,如从数据源创建 Stream,以及中间和终端操作。通过过滤、映射、归并、排序、分组等案例,展示了 Streams 的使用,包括并行 Streams 提高效率。学习 Streams 可以提升代码质量和效率,文章鼓励读者在实际开发中探索更多 Streams 功能。