Java语法相关知识汇总(六)

 第四章、Collection集合(单个方式存储元素)

一、创建集合

        在Java中,可以使用多种方式来创建一个集合对象,具体取决于你想要使用的集合类型和需求。下面列举了几种常见的创建集合的方式:

1、使用具体的集合实现类的构造方法

可以直接实例化具体的集合实现类,例如ArrayListLinkedListHashSet等。

ArrayList<String> arrayList = new ArrayList<>();  // 创建一个ArrayList集合
        HashSet<Integer> hashSet = new HashSet<>();     // 创建一个HashSet集合

2、使用Collection,List,Set,SortedSet接口的实现类的构造方法

Collection是一个接口,但是你可以通过具体的实现类来实例化集合对象。

Collection<String> collection = new ArrayList<>();  // 创建一个ArrayList集合

二、集合遍历/迭代器(Iterator接口)

  • 以下的遍历方式/迭代方式,是所有Collection集合的通用方式,在Map集合中不能用,在所有的Collection及其子类中使用
  • 在Java中,迭代器(Iterator)是一种用于遍历集合(Collection)元素的对象。它提供了一些方法来逐个访问集合中的元素。

1、集合对象实例方法 iterator( ):获取集合对象的迭代器对象

//创建集合对象
Collection c = new ArrayList(); //后面的集合无所谓,主要是看前面的接口,怎么迭代
//第一步:获取集合对象的迭代器对象
Iterator it = c.iterator();
System.out.println(it); //java.util.ArrayList$Itr@7ef20235

2、boolean hasNext():该方法用于检查迭代器中是否还有下一个元素。如果有下一个元素,则返回true;否则,返回false

//创建集合对象
Collection c = new ArrayList();

c.add(1);
c.add(2);

Iterator it = c.iterator();
boolean flag = it.hasNext();
it.next();
System.out.println(flag); //true

flag = it.hasNext();
it.next();
System.out.println(flag); //true

flag = it.hasNext();
System.out.println(flag); //false

3、E next():该方法用于返回迭代器中的下一个元素,并将迭代器的位置移动到下一个元素。(E泛型默认为Object,泛型类型擦除)

while (it.hasNext()){
    Object obj = it.next();
    System.out.println(obj); //1 2
}

//运行时异常: java.util.NoSuchElementException
//        while (true){
//            Object obj = it.next();
//            System.out.println(obj);
//        }

4、void remove():该方法用于从集合中移除迭代器当前next返回的元素。此方法只能在调用next()之后,并且在同一次迭代中只能调用一次。

  • 在迭代集合元素的过程中,一定要使用迭代器对象的remove() 方法来删除元素,不能使用集合对象的remove()方法来删除元素
  • 需要注意的是,如果在迭代器的next()方法之前调用了remove()方法,或者在同一次迭代中多次调用remove()方法,都会导致IllegalStateException(非法状态)异常的抛出。

package com.javase.collection;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

/**
 * 关于集合元素的remove
 * 集合就像快照一样,当集合结构发生改变时,必须重新获取迭代器,否则调用next()方法:java.util.ConcurrentModificationException,并发修改异常
 *
 * 在迭代集合元素的过程中,不能调用集合对象的remove方法,删除元素;
 *      c.remove(); 迭代过程中不能这样
 *      会出现:java.util.ConcurrentModificationException
 *
 * 在迭代集合元素的过程中,一定要使用迭代器对象的remove方法来删除元素
 */
public class CollectionTest06 {
    public static void main(String[] args) {
        //创建集合
        Collection c = new ArrayList();

        /**
         * 注意:此时获取的迭代器,指向的是集合中没有元素状态下的迭代器
         * 一定要注意:集合结构只要发生改变,迭代器必须重新获取
         * 当集合结构发生改变,迭代器没有重新获取时,调用next()方法:java.util.ConcurrentModificationException
         */
//        Iterator it = c.iterator();
        //添加元素
        c.add(1); //Integer类型,自动装箱
        c.add(2);
        c.add(3);
        //循环集合
        Iterator it = c.iterator();
        while (it.hasNext()){
            //编写代码时next()方法返回值类型必须是Object
            //因为泛型类型擦除为Object
            Object obj = it.next();
            System.out.println(obj); //1 2 3
        }

        Collection c2 = new ArrayList();
        c2.add("abc");
        c2.add("def");
        c2.add("xyz");
        Iterator it2 = c2.iterator();
        while (it2.hasNext()){
            Object obj = it2.next();
            //删除元素
            //删除元素之后,集合的结构发生了变化,应该重新获取迭代器
            //但是,循环下一次的时候并没有重新获取迭代器,所以会出现异常:java.util.ConcurrentModificationException
//            c2.remove(obj); //直接通过集合去删除元素,没有通知迭代器(导致迭代器的快照和原集合状态不同。)
            //迭代器删除时,会自动更新迭代器,并且更新原集合
            it2.remove();
            System.out.println(obj); //abc def xyz
        }
        System.out.println(c2.size()); //0
    }
}

5、迭代器执行原理

6、不使用泛型的情况下迭代器的next()方法,返回默认为Object类型

package com.javase.collection;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

/**
 * 关于集合遍历/迭代专题
 */
public class CollectionTest02 {
    public static void main(String[] args) {
        //注意:以下讲解的遍历方式/迭代方式,是所有的Collection通用的方式
        //在Map集合中不能用,在所有的Collection及其子类中使用

        //创建集合对象
        Collection c = new ArrayList(); //后面的集合无所谓,主要是看前面的接口,怎么迭代
        //添加元素
        c.add("abc");
        c.add("def");
        c.add(100);
        c.add(new Object());

        //对集合Collection进行遍历/迭代

        //第一步:获取集合对象的迭代器对象
        Iterator it = c.iterator();

        //第二步:通过获取的迭代器对象开始迭代/遍历
        /**
         * 以下两个方法是迭代器对象Iterator中的方法:
         *      boolean hasNext() 如果仍有元素可迭代,则返回true
         *      Object next() 返回迭代的下一个元素
         */

        /*boolean hasNext = it.hasNext();
        System.out.println(hasNext);
        if(hasNext){
            //不管你当初存进去什么,取出来统一都是Object
            Object obj = it.next();
            System.out.println(obj);
        }

        hasNext = it.hasNext();
        System.out.println(hasNext);
        if(hasNext){
            Object obj = it.next();
            System.out.println(obj);
        }

        hasNext = it.hasNext();
        System.out.println(hasNext);
        if(hasNext){
            Object obj = it.next();
            System.out.println(obj);
        }

        hasNext = it.hasNext();
        System.out.println(hasNext);
        if(hasNext){
            Object obj = it.next();
            System.out.println(obj);
        }

        hasNext = it.hasNext();
        System.out.println(hasNext);
        if(hasNext){
            Object obj = it.next();
            System.out.println(obj);
        }*/

        while (it.hasNext()){
            Object obj = it.next();
            System.out.println(obj);
        }

        //运行时异常: java.util.NoSuchElementException
//        while (true){
//            Object obj = it.next();
//            System.out.println(obj);
//        }
    }
}

 7、存进去的是什么类型,取出来的还是什么类型,只不过输出的时候会转换成字符串

package com.javase.collection;

import java.util.*;

public class CollectionTest03 {
    public static void main(String[] args) {
        //ArrayList集合特点;有序可重复
        //创建集合
        Collection c = new ArrayList();

        //添加元素
        c.add(1);
        c.add(2);
        c.add(2);
        c.add(3);
        c.add(4);
        c.add(4);

        //迭代集合
        //创建迭代器
        Iterator it = c.iterator();

        //开始迭代
        while (it.hasNext()){
            //存进去的是什么类型,取出来的还是什么类型
            Object obj = it.next();
            if(obj instanceof Integer){
                System.out.println("Integer类型");
            }
            //只不过在输出的时候会转换成字符串,因为这里println会调用toString()方法
            System.out.println(obj);
            /**
             * Integer类型
             * 1
             * Integer类型
             * 2
             * Integer类型
             * 2
             * Integer类型
             * 3
             * Integer类型
             * 4
             * Integer类型
             * 4
             */
        }

        //HashSet集合特点:无序不可重复
        Collection c2 = new HashSet();
        //无序:存进去和取出来的顺序不一定相同
        //不可重复:存储100,不能再存储100
        c2.add(100);
        c2.add(200);
        c2.add(300);
        c2.add(80);
        c2.add(500);
        c2.add(360);
        c2.add(100);
        c2.add(100);

        Iterator it2 = c2.iterator();
        while (it2.hasNext()){
            System.out.println(it2.next());
            /**
             * 80
             * 100
             * 500
             * 200
             * 360
             * 300
             */
        }
    }
}

 8、集合结构只要发生改变,迭代器必须重新获取

package com.javase.collection;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

/**
 * 关于集合元素的remove
 * 集合就像快照一样,当集合结构发生改变时,必须重新获取迭代器,否则调用next()方法:java.util.ConcurrentModificationException
 */
public class CollectionTest06 {
    public static void main(String[] args) {
        //创建集合
        Collection c = new ArrayList();

        /**
         * 注意:此时获取的迭代器,指向的是集合中没有元素状态下的迭代器
         * 一定要注意:集合结构只要发生改变,迭代器必须重新获取
         * 当集合结构发生改变,迭代器没有重新获取时,调用next()方法:java.util.ConcurrentModificationException
         */
        Iterator it = c.iterator();
        //添加元素
        c.add(1); //Integer类型
        c.add(2);
        c.add(3);
        //循环集合
//        Iterator it = c.iterator();
        while (it.hasNext()){
            //编写代码时next()方法返回值类型必须是Object
            Object obj = it.next();
            System.out.println(obj);
        }
    }
}

9、ArrayList实现迭代器源码

三、Collection接口中常用实例方法

集合中的元素对象一定要重写equals方法

        在Java中,Collection接口是Java集合框架的根接口之一,它定义了一组通用的方法,可以用于操作和管理集合对象。

1、Collection接口中存放的元素

没有使用“泛型”之前,Collection中可以存储Object的所有子类型

使用了“泛型”之后,Collection中只能存储某个具体的类型

2、boolean add(E element):将指定元素添加到集合末尾

Collection collection = new ArrayList();
collection.add(100); //自动装箱,实际上是放进去了一个Integer类型的对象的引用
collection.add(3.14); //自动装箱
System.out.println(collection.add(new Object())); //true
//List集合特点:有序可重复
collection.add(true); //自动装箱 
System.out.println(collection.add(true)); // true  自动装箱

3、int size():返回集合中的元素个数

//获取集合中元素的个数
System.out.println("集合中元素的个数:" + collection.size()); //集合中元素的个数:5

4、void clear():从集合中移除所有元素

//清空集合
collection.clear();
System.out.println("集合中元素的个数:" + collection.size()); //集合中元素的个数:0

5、boolean contains(Object element):判断集合是否包含指定元素(element),包含返回true,不包含返回false

//再向集合中添加元素
collection.add("hello"); //“hello”对象的内存地址放到了集合中
collection.add("world");

//判断集合中是否包含“hello”
boolean flag = collection.contains("hello");
System.out.println(flag); //true

System.out.println(collection.contains("jzq")); //false

5.1、contains原理解析

contains方法底层通过遍历集合中元素,调用equals方法将集合中元素和目标元素进行对比

若equals方法返回true,则表示包含这个元素

若equals方法返回false,则表示不包含这个元素

源码分析

案例一:String类已经重写了equals方法,比较内容

package com.javase.collection;

import java.util.ArrayList;
import java.util.Collection;

/**
 * 深入Collection集合中contains方法;
 *      boolean contains(Object element):判断集合是否包含指定元素(element),包含返回true,不包含返回false
 *
 *      contains方法是用来判断集合中是否包含某个元素的方法
 *      那么它在底层是如何判断是否包含某个元素的尼?
 *          contains方法底层通过遍历集合中元素,调用equals方法将集合中元素和目标元素进行对比
 *          若equals方法返回true,则表示包含这个元素
 *          若equals方法返回false,则表示不包含这个元素
 */
public class CollectionTest04 {
    public static void main(String[] args) {
        //创建集合对象
        Collection c = new ArrayList();

        //向集合中添加元素
        String s1 = new String("abc");
        c.add(s1);

        String s2 = new String("def");
        c.add(s2);

        //集合中元素的个数:
        System.out.println("集合中元素的个数:" + c.size()); //2

        String x = new String("abc");
        System.out.println(c.contains(x)); //true
    }
}

案例二:未重写equals方法,比较内存地址

package com.javase.collection;

import java.util.ArrayList;

/**
 * 测试contains方法
 */
public class CollectionTest05 {
    public static void main(String[] args) {
        //创建集合对象
        ArrayList arrayList = new ArrayList();

        //创建用户对象
        User u1 = new User("jzq");
        User u2 = new User("jzq");

        //加入集合
        arrayList.add(u1);

        //判断集合中是否包含u2
        //没有重写equals方法之前,这个结果是false
        //System.out.println(arrayList.contains(u2)); //false

        //重写equals方法之后,这个结果是true
        System.out.println(arrayList.contains(u2)); //true

        //举个例子:因为Integer类重写了equals方法,比较内容
        Integer x = new Integer(10000);
        arrayList.add(x);

        Integer y = new Integer(10000);

        System.out.println(arrayList.contains(y)); //true
    }
}

class User{
    private String name;
    public User(){}
    public User(String name){
        this.name = name;
    }

    public boolean equals(Object obj){
        if(null == obj || !(obj instanceof User)){
            return false;
        }
        if (this == obj){
            return true;
        }
        User u = (User) obj;
        //比较内容,如果名字一样则返回true(比较内容)
        return this.name.equals(u.name);
    }
}

6、boolean remove(Object element):从集合中移除指定的第一个元素

移除集合中某个值的第一个匹配项

System.out.println("集合中元素的个数:" + collection.size()); //2
//删除集合中指定的元素
collection.remove("hello");
System.out.println("集合中元素的个数:" + collection.size()); //1

6.1、remove原理解析

源码分析

 案例:String类已经重写了equals方法,比较内容,所以删除s2是将s1删除

package com.javase.collection;

import java.util.ArrayList;
import java.util.Collection;

public class CollectionTest06 {
    public static void main(String[] args) {
        //创建集合对象
        Collection c = new ArrayList();
        //创建字符串对象
        String s1 = new String("jzq");
        //加入集合
        c.add(s1);
        //创建新的字符串对象
        String s2 = new String("jzq");
        //删除s2
        c.remove(s2);
        //集合中元素个数
        System.out.println(c.size()); //0

        List<? super String> list = new ArrayList<>();
        list.add("jzq");
        list.add("jzq");
        System.out.println(list.size()); //2

        list.remove("jzq");
        System.out.println(list.size()); //1
    }
}

7、boolean isEmpty():判断集合是否为空,为空返回true,不为空返回false

源码:

//判断集合是否为空(集合中是否存在元素)
System.out.println(collection.isEmpty()); //false
//清空
collection.clear();
System.out.println(collection.isEmpty()); //true

8、Object[] toArray():将集合转换为一个数组

collection.add(1);
collection.add(2);
collection.add("jzq");
collection.add(new Student());

//转换为数组
//编译报错:toArray方法返回值类型为Object[] 一维数组,则必须使用Object[]类型声明,不能使用其子类型
//Integer[] objs = collection.toArray();

Object[] objects = collection.toArray();
System.out.println(Arrays.toString(objects)); //[1, 2, jzq, com.javase.collection.Student@b4c966a]

四、List接口中特有常用实例方法

在Java中,List接口是一种有序的集合,允许重复元素。它扩展了Collection接口,并添加了一些特定于列表操作的方法。

1、void add(int index, E element):在指定索引位置插入指定元素,index是索引(使用较少)

//创建集合
List list = new ArrayList();

//添加元素
list.add("A");
list.add("B");
list.add("C");
list.add("D");
//void add(int index, E element):在指定索引位置插入指定元素
//这个方法使用不多,因为对于ArrayList集合来说效率较低,ArrayList底层是数组,涉及到元素位移问题
list.add(1,"KING");

//迭代集合
Iterator it = list.iterator();
while (it.hasNext()){
    Object obj = it.next();
    System.out.println(obj.toString()); // A KING B C D
}

2、E get(int index):返回指定索引位置的元素

//E get(int index):返回指定索引位置的元素
Object firstElement = list.get(0);
System.out.println(firstElement); //A

3、int indexOf(Object element):返回指定元素在列表中首次出现的索引

//int indexOf(Object element):返回指定元素在列表中首次出现的索引
int index =  list.indexOf("KING");
System.out.println(index); //1

4、int lastIndexOf(Object element):返回指定元素在列表中最后一次出现的索引

//int lastIndexOf(Object element):返回指定元素在列表中最后一次出现的索引
int index1 = list.lastIndexOf("D");
System.out.println(index1); //4

5、E remove(int index):移除指定索引位置的元素,并将删除的元素返回

//E remove(int index):移除指定索引位置的元素
Object s = list.remove(0);
System.out.println(s); //A
System.out.println(list.size()); //4
System.out.println(list); //[KING, B, C, D]

6、E set(int index, E element):将指定索引位置的元素替换为新元素,并将原来位置处的元素返回

//E set(int index, E element):将指定索引位置的元素替换为新元素
Object obj = list.set(2,"SOFT");
System.out.println(obj); //C
System.out.println(list); //[KING, B, SOFT, D]

7、List集合特有的遍历集合方式(采用get方法)

//除了迭代器之外另外遍历集合的方式:采用索引遍历
for (int i = 0; i < list.size(); i++) {
    Object ele = list.get(i);
    System.out.println(ele);
}

8、遍历List集合的三种方式

package com.javase.collection.forEach增强for循环;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * 集合使用foreach
 */
public class ForEachTest02 <T>{
    public static void main(String[] args) {

        //创建list集合
        List<String> list = new ArrayList<>();
        ForEachTest02<String> f = new ForEachTest02<>();
        //添加元素
        list.add("Hello");
        list.add("world");
        list.add("kitty");

        //遍历,采用迭代器方式
        f.demo1(list);
        System.out.println("===================");
        //采用get索引方式
        f.demo2(list);
        System.out.println("===================");
        //采用foreach方式
        f.demo3(list);
    }
    
    //第三种方式:iterator迭代器
    public void demo1(List<T> list){
        Iterator<T> it = list.iterator();
        while (it.hasNext()){
            T obj = it.next();
            System.out.println(obj);
        }
    }
    
    //第二种方式:for循环
    public void demo2(List<T> list){
        for (int i = 0; i < list.size(); i++) {
            T obj = list.get(i); //list集合特有的方法
            System.out.println(obj);
        }
    }
    
    //第一种方式:foreach循环
    public void demo3(List<T> list){
        for (T element:
             list) {
            System.out.println(element);
        }
    }
}

五、ArrayList实现类

        在Java中,ArrayList是一种实现了List接口的动态数组,它提供了一种便捷的方式来操作元素集合。

1、ArrayList的特点

1.1、动态数组

        ArrayList内部使用数组来存储元素,它可以根据需要动态增长或缩小数组的大小。当添加元素超过当前数组的容量时,ArrayList会自动扩容,通常以当前容量的一定比例进行扩展。

1.2、有序集合

ArrayList中的元素按照添加的顺序进行存储,它保持元素的插入顺序,并允许通过索引访问元素。

1.3、允许重复元素

ArrayList可以存储重复的元素,不会对元素的唯一性进行限制。

1.4、随机访问

ArrayList支持通过索引快速访问元素,由于底层使用数组存储,因此可以根据索引在常数时间内访问特定位置的元素。

1.5、插入和删除效率较低

        由于ArrayList是基于数组实现的,当需要在中间位置插入或删除元素时,需要移动后续元素来填补空缺或者重新分配数组的内存空间,因此插入和删除操作的效率较低

1.6、不适合频繁的插入和删除操作

由于插入和删除操作的效率较低,当需要频繁进行插入和删除操作时,LinkedList可能是更好的选择。

1.7、非线程安全

ArrayList不是线程安全的,如果在多线程环境下使用ArrayList,需要自行考虑线程同步的问题。

        总的来说,ArrayList适用于需要频繁随机访问元素、根据索引进行操作的场景,对于插入和删除操作不太频繁的情况下,它提供了高效的操作方式

1.8、ArrayList集合初始化容量为10(底层先创建了一个长度为0的数组,当添加第一个元素的时候,初始化容量为10)

        在Java中,ArrayList是通过数组实现的动态数组,其源码中有一个常量 DEFAULTCAPACITY

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值