详解Java中集合的List接口实现的ArrayList方法 | Set接口实现的HashSet方法

简介: 详解Java中集合的List接口实现的ArrayList方法 | Set接口实现的HashSet方法

集合的概念

 当我们需要保存一组一样(类型相同)的元素的时候,我们应该使用一个容器来存储,数组就是    这样一个容器。

数组的特点:    

  数组是一组数据类型相同的元素集合;

  创建数组时,必须给定长度,而且一旦创建长度不能改变;

  一旦数组装满元素,就需要创建一个新的数组,将元素复制过去;

数组的局限:

  如果装满了,就需要数组复制;

  当我们需要从数组中删除或添加一个元素,需要移动后面的元素;

集合的作用:

  在开发实践中,我们需要一些能够动态增长长度的容器来保存我们的数据,java中为了解决数据    存储单一的情况,java中就提供了不同结构的集合类,可以让我们根据不同的场景进行数据存储     的选择,如Java中提供了 数组实现的集合,链表实现的集合,哈希结构,树结构等。

分类

单列集合:    一次放进去一个值 ( 对象 )

  Collection接口:定义了单列集合共有的方法,其子接口Set和List分别定义了存储方式

List:可以有重复元素

Set:不可以有重复元素

双列集合:     键     值

集合API

集合体系概述: Java的集合框架是由很多接口、抽象类、具体类组成的,都位于java.util包中。

List 接口及实现类

概念:List接口继承了Collection接口,有三个实现的类,分别是:

ArrayList       数组列表

LinkedList    链表列表

Vector           数组列表 (是线程安全的)

1.  ArrayList

● 底层有一个数组,可以动态扩展数组长度,并提供了一系列方法操作。

特点: 查询快,在中间增加 / 删除慢。

注意:集合容器类中默认可以添加Object类型,但是一般建议一个集合对象只保存同一种类型,若保存多个类型后期处理时涉及类型转换问题;所以我们可以通过泛型来加以控制。

泛型:声明类型时可以自定义参数类型。

             ArraysList  <E>

ArrayList的常用方法:

ArrayList<String> arrayList = new ArrayList();
        arrayList.add("a");
        arrayList.add("b");
        arrayList.add("c");
        arrayList.add(3,"a");
       
        arrayList.remove("a");  //根据内容删除匹配的第一个元素,返回值为boolean
        arrayList.remove(1);    //删除并返回指定位置的元素
        arrayList.get(1);         //获取指定位置的元素
        arrayList.set(1,"X");     //替换并返回指定位置的元素
        arrayList.clear();        //清空集合中的元素
        arrayList.isEmpty();      //判断集合元素是否为空
        arrayList.contains("c");  //判断是否包含指定元素
        arrayList.size();         //返回集合中元素个数

2.  LinkedList

● 底层是一个链表结构; 特点: 查询效率低,但增加 / 删除元素快。

● LinkedList中方法及功能和ArrayList中的方法大致相同,只不过LinkedList中多了关于队列相     关的操作方法。

3.  Vector

● 和ArrayList一样,底层也是数组实现,不同的是Vector的方法默认加了锁线程是安全的

List接口集合迭代

List集合遍历方式有四种:

●  1.  for循环遍历          ● 2.  增强for循环遍历  

        //List集合遍历方式1:for循环
        for (int i = 0; i < arrayList.size(); i++) {
            if ("a".equals(arrayList.get(i))){
                arrayList.remove("a");//允许修改集合元素
                i--;            // 要注意索引的变化与元素位置的移动
            }
            
        }
        System.out.println(arrayList);
        System.out.println("----------------");
        
        //List集合遍历方式2:增强for循环
        for (String s:arrayList) {
            System.out.println(s);   //不能修改集合元素
        }

3.  迭代器遍历 (Iterator)

        //List集合遍历方式3:使用迭代器遍历
        //获得集合对象的迭代器对象
       Iterator<String> it = arrayList.iterator();
        while(it.hasNext()){
            String s = it.next();//获取下一个院系
            if (s.equals("a")) {
                it.remove();  //使用迭代器对象删除元素
            }
        }
        System.out.println(arrayList);

4.  ListIterator迭代器:

public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList();
        arrayList.add("a");
        arrayList.add("b");
        arrayList.add("c");
        arrayList.add("d");
        /*
         ListIterator迭代器只能对List接口下的实现遍历
         ListIterator(index)可以从指定位置开始向前向后遍历
         */
        ListIterator<String> listIterator= arrayList.listIterator(arrayList.size());
        while(listIterator.hasPrevious()){
            System.out.println(listIterator.previous());//逆序遍历
        }
    }

Set接口

● Set接口也继承了Collection接口,Set中所储存的元素是不重复的,但是是无序的,Set中的元素     没有索引。

Set接口的实现类

HashSet

● HashSet类中的元素不能重复.

 public static void main(String[] args) {
        HashSet set =new HashSet<>();
        set.add("a");
        set.add("a");
        set.add("b");
        set.add("c");    //元素是不重复的
        System.out.println(set);
    }

● HashSet类中的元素是无序的 .

public static void main(String[] args) {
        HashSet set =new HashSet<>();
        set.add("c");
        set.add("s");
        set.add("x");
        set.add("d");    //元素是无序的
        System.out.println(set);
 
        set.remove("s");//没有索引,只能根据内容遍历
        set.iterator();//没有索引,要用迭代器遍历
 
    }

元素不重复原理

 HashSet在添加元素时,是如何判断元素重复的?       

在底层会先调用hashCode(),注意,Object中的hashCode()返回的是对象的地址,此时并不会调用;此时调用的是类中重写的hashCode(),返回的是根据内容计算的哈希值,遍历时,会用哈希值先比较是否相等,会提高比较的效率;但哈希值会存在问题:内容不同,哈希值相同;这种情况下再调equals比较内容,这样既保证效率又确保安全。


例:

这是错误写法,此时默认调用的是Object类中hashCode( ),返回对象地址

import java.util.HashSet;
import java.util.Objects;
 
public class Student {
    private String name ;
    private String num;
 
 
    public Student(String name, String num) {
        this.name = name;
        this.num = num;
    }
 
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", num='" + num + '\'' +
                '}';
    }
    
        public static void main(String[] args) {
            HashSet<Student> set = new HashSet<>();
            Student s1 = new Student("小王1","10001");
            Student s2 = new Student("小王2","10002");
            Student s3 = new Student("小王3","10003");
            Student s4 = new Student("小王1","10001");
            set.add(s1);
            set.add(s2);
            set.add(s3);
            set.add(s4);
            System.out.println(set);
            
        }
    }

正确写法应该是,在Student类中重写hashCode()和equals()

package Demo;
 
import java.util.HashSet;
import java.util.Objects;
 
public class Student {
    private String name ;
    private String num;
 
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return num.equals(student.num);
    }
 
    @Override
    public int hashCode() {
        return Objects.hash(num);
    }
 
    public Student(String name, String num) {
        this.name = name;
        this.num = num;
    }
 
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", num='" + num + '\'' +
                '}';
    }
 
        public static void main(String[] args) {
            HashSet<Student> set = new HashSet<>();
            Student s1 = new Student("小王1","10001");
            Student s2 = new Student("小王2","10002");
            Student s3 = new Student("小王3","10003");
            Student s4 = new Student("小王1","10001");
            set.add(s1);
            set.add(s2);
            set.add(s3);
            set.add(s4);
            System.out.println(set);
 
        }
    }
 

这样就能避免重复了(此图是s1,s4重复,但只输出s1)


补充:如何快速生成hashCode()和equals()的重写方法?

  右键选择Generate,选择equals()and hashCode(),选择重写的属性即可.


TreeSet

敬请期待...

相关文章
|
5月前
|
存储 Java 索引
(Python基础)新时代语言!一起学习Python吧!(二):字符编码由来;Python字符串、字符串格式化;list集合和tuple元组区别
字符编码 我们要清楚,计算机最开始的表达都是由二进制而来 我们要想通过二进制来表示我们熟知的字符看看以下的变化 例如: 1 的二进制编码为 0000 0001 我们通过A这个字符,让其在计算机内部存储(现如今,A 字符在地址通常表示为65) 现在拿A举例: 在计算机内部 A字符,它本身表示为 65这个数,在计算机底层会转为二进制码 也意味着A字符在底层表示为 1000001 通过这样的字符表示进行转换,逐步发展为拥有127个字符的编码存储到计算机中,这个编码表也被称为ASCII编码。 但随时代变迁,ASCII编码逐渐暴露短板,全球有上百种语言,光是ASCII编码并不能够满足需求
255 4
|
8月前
|
并行计算 Java API
Java List 集合结合 Java 17 新特性与现代开发实践的深度解析及实战指南 Java List 集合
本文深入解析Java 17中List集合的现代用法,结合函数式编程、Stream API、密封类、模式匹配等新特性,通过实操案例讲解数据处理、并行计算、响应式编程等场景下的高级应用,帮助开发者提升集合操作效率与代码质量。
378 1
|
8月前
|
存储 安全 Java
Java 学习路线 35 掌握 List 集合从入门到精通的 List 集合核心知识
本文详细解析Java中List集合的原理、常用实现类(如ArrayList、LinkedList)、核心方法及遍历方式,并结合数据去重、排序等实际应用场景,帮助开发者掌握List在不同业务场景下的高效使用,提升Java编程能力。
546 0
|
Java 机器人 程序员
从入门到精通:五种 List 遍历方法对比与实战指南
小米是一位热爱分享技术的程序员,本文详细介绍了 Java 中遍历 List 的五种方式:经典 for 循环、增强 for 循环、Iterator 和 ListIterator、Stream API 以及 forEach 方法。每种方式都有其适用场景和优缺点,例如 for 循环适合频繁访问索引,增强 for 循环和 forEach 方法代码简洁,Stream API 适合大数据量操作,ListIterator 支持双向遍历。文章通过生动的小故事和代码示例,帮助读者更好地理解和选择合适的遍历方式。
714 2
|
安全 Java 程序员
深入Java集合框架:解密List的Fail-Fast与Fail-Safe机制
本文介绍了 Java 中 List 的遍历和删除操作,重点讨论了快速失败(fail-fast)和安全失败(fail-safe)机制。通过普通 for 循环、迭代器和 foreach 循环的对比,详细解释了各种方法的优缺点及适用场景,特别是在多线程环境下的表现。最后推荐了适合高并发场景的 fail-safe 容器,如 CopyOnWriteArrayList 和 ConcurrentHashMap。
342 5
|
NoSQL Java Redis
List集合按照由小到大排序或者由大到小排序
List集合按照由小到大排序或者由大到小排序
320 0
|
5月前
|
存储 JavaScript Java
(Python基础)新时代语言!一起学习Python吧!(四):dict字典和set类型;切片类型、列表生成式;map和reduce迭代器;filter过滤函数、sorted排序函数;lambda函数
dict字典 Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。 我们可以通过声明JS对象一样的方式声明dict
366 1
|
8月前
|
存储 缓存 JavaScript
Set和Map有什么区别?
Set和Map有什么区别?
592 1
|
5月前
|
存储 算法 容器
set_map的实现+set/map加持秒杀高频算法题锻炼算法思维
`set`基于红黑树实现,支持有序存储、自动去重,增删查效率为O(logN)。通过仿函数可自定义排序规则,配合空间配置器灵活管理内存。不支持修改元素值,迭代器失效需注意。`multiset`允许重复元素。常用于去重、排序及查找场景。
|
9月前
|
存储 JavaScript 前端开发
for...of循环在遍历Set和Map时的注意事项有哪些?
for...of循环在遍历Set和Map时的注意事项有哪些?
438 121