14 Java集合(集合框架+泛型+ArrayList类+LinkedList类+Vector类+HashSet类等)

简介: 14 Java集合(集合框架+泛型+ArrayList类+LinkedList类+Vector类+HashSet类等)

14.1 集合框架

什么是集合框架?

Java中的集合框架其实就是对**【数据结构】**的封装,这个封装中提供了一些常用方法,可方便操作数据,无需程序猿自定定义操作,只需要调用封装方法就可以完成对存在集合中数据【增删改查】

集合其实就是对数据结构一种封装,所以之前sun公司就把集合放置到一个统一包中进行管理【java.util】包


什么是数据结构?

数据结构其实就是计算机,组织和存储数据形式

数据结构是指相互之间存在一种或多种特定关系的数据集合

通常情况下,精心选择数据结构可以带来更加高效运行和存储效率, 数据结构往往高效的原因在于**【检索算法】和【索引计数】**

常见数据结构:【数组、栈、链表(单向和双向)、哈希表、队列(单向和双向)、堆、树、图】

Java的集合框架其实就是对【数据结构实现】,我们需要掌握就是如何操作这个数据结构(即操作集合中方法),高效存储与处理数据

PS:根据不同数据结构,操作数据性能是不同(有地查询块、有的插入快、有地允许重复、有的不允许重复等等),在开发中只要选择合理数据结构即集合对数据存储与操作即可


Java中常见的集合框架


习惯性说Java中集合有三大框架【List、Set和Map】


如果详细说明的话应该2个框架3个实现


2个框架: Collection 和 Map

3个实现 :Collection这个集合下两个主要实现 List 和 set 所以称为三大集合List、set 和Map

集合和数组最大区别在于:


集合中只能储存引用类型即对象

集合是一个变长容量,根据集合储存元素个数动态进行删减【扩容和减容】

数组是一个定长容器,创建大小数固定,无论存储多少数据长度都是唯一

常见三大集合框架:


List【列表】:集合中存储对象是按照索引位置进行存储,允许存储重复数据

Set【集】: 集合中存储对象不是按照特定方式进行存储,不允许出现重复数据

Map【映射】:集合中每一个存储元素都是以一种【键值对key- value】方式进行存储的,以一种key和value的形式存储的,key 这个对象是不允许重复【唯一性】,value是允许重复

14.1.1 概念
  • 集合是一种对象容器,用于存放对象
  • 数组的缺点:
  • 1、数组定长,一旦定义不能改变
  • 2、数组中没有方法
  • 3、数组中只能存放相同的数据类型的数据
  • 集合特点:
  • 1、长度可以改变
  • 2、集合中丰富的操作元素的方法
  • 3、集合中只能存储引用数据类型的数据
  • 集合的分类
  • 1、单列集合 (集合中一个元素保存一个数据) Collection
  • 2、双列集合 (集合中一个元素保存两个数据) Map
14.1.2 集合架构
集合架构

image.png

14.2 Collection接口

单列集合的顶层接口

14.2.1 常用方法
  • add方法向集合集合中添加元素
  • clear方法,清空集合中所有元素
  • contains方法 判断集合是否包含某个元素
  • isEmpty判断集合是否为空
  • remove方法 移除集合中元素,返回boolean类型。如果集合中不包含次元素,则删除失败
  • size()返回集合中元素的个数
  • toArray将集合转换成数组。
  • addAll 向一个集合中添加另一个集合
  • containsAll 判断一个集合中是否包含另一个集合
  • removeAll 从一个集合中移除另一个集合
public class CollectionDemo {
  public static void main(String[] args) {
    //创建Collection对象
    Collection coll = new ArrayList();
    
    //Collection接口下常用的方法
    
    //add   向集合中添加元素
    coll.add("jack");
    coll.add(10);
    coll.add("rose");
    
    System.out.println(coll);
    
    //contains 判断集合中是否包含指定元素
    System.out.println(coll.contains("赵四"));
    
    //isEmpty  判断集合的元素个数是否为0     
    System.out.println(coll.isEmpty());
    
    //remove   移除集合中指定的元素,如果存在返回true、否则返回false
    coll.remove("jack1");
    System.out.println(coll);
    
    //size    获取集合中元素个数
    System.out.println(coll.size());
    
    //toArray 将集合变成数组 
    Object[] arr = coll.toArray();
    
    //Arrays.toString  将数组变成字符串形式
    System.out.println(Arrays.toString(arr));
    
    int[] nums = {1,2,3,4};
    //将数组转成集合
    List asList = Arrays.asList(nums);
    System.out.println(asList);
    
    
    Collection coll1 = new ArrayList();
    coll1.add("lilei");
    coll1.add("hanmeimei");
    //addAll   将另一个集合中元素添加到当前集合中
    coll1.addAll(coll);
    System.out.println(coll1);
    //containsAll  判断集合中是否包含另一个集合
    System.out.println(coll1.containsAll(coll));
//    coll1.removeAll(coll);
//    System.out.println(coll1);
    
    //retainAll  保留coll中包含的元素
    coll1.retainAll(coll);
    System.out.println(coll1);
  }
}

14.3 迭代器

14.3.1 迭代器原理

迭代是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果。每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值。

迭代器原理

image.png

//迭代器的作用:获取集合中的所有的元素    
Collection coll = new ArrayList();
coll.add("jack");
coll.add("rose");
coll.add(10);
coll.add(20.2);
//1、获取迭代器对象
Iterator it = coll.iterator();
while(it.hasNext()) {
    System.out.println(it.next());
}
System.out.println(coll);
14.3.2 迭代器使用常见问题
  • 1、迭代器迭代完成之后,迭代器的位置在最后一位。 所以迭代器只能迭代一次
  • 2、迭代器在迭代的时候,不要调用多次next方法,可能会出错 NoSuchElementException
  • 3、在迭代器迭代的时候,不能向集合中添加或者删除元素 ConcurrentModificationException
public class IteratorDemo {
  public static void main(String[] args) {
    //使用迭代器需要注意的问题
    
    //1、迭代器只能使用一次
//    Collection coll = new ArrayList();
//    coll.add("jack");
//    coll.add("rose");
//    coll.add(10);
//    coll.add(20.2);
//    Iterator it = coll.iterator();
//    while(it.hasNext()){
//      System.out.println(it.next());
//    }
//    while(it.hasNext()){
//      System.out.println(it.next());
//    }
    
    //2、迭代器使用的时候不能多次使用next方法
//    Collection coll = new ArrayList();
//    coll.add("jack");
//    coll.add("rose");
//    coll.add(10);
//    coll.add(20.2);
//    coll.add(100);
//    Iterator it = coll.iterator();
//    while(it.hasNext()) {
//      Object obj = it.next();
//      System.out.println(it.next());
//    }
    //3、迭代器在迭代的时候不要添加或者删除元素
    Collection coll = new ArrayList();
    coll.add("jack");
    coll.add("rose");
    coll.add(10);
    coll.add(20.2);
    coll.add(100);
    Iterator it = coll.iterator();
    while(it.hasNext()) {
      coll.remove(10);
      //coll.add("zhaosi");
      System.out.println(it.next());
    }
  }
}

14.4 泛型基本使用

泛型:参数化类型 JDK1.5之后

  • 用途:
  • 因为如果不使用泛型,那么向集合中添加元素,实际当做Object对象传递进去的,此时发生向上转型了当从集合中获取数据,得到的是Object类型,那么在使用的需要向下转型,,才能正常使用。因此频繁向上向下转型。可能会出现类转换异常。 这个时候就需要使用泛型。
  • 泛型的作用实际上就是讲类型转换的检查提前到了编译期
  • 泛型擦除: JDK1.7之后
  • 集合类型<泛型> 变量名 = new 集合类型<>();
  • 泛型需要注意的问题:
  • 1、泛型上不存在多态
  • Collection coll = new ArrayList();//错误
  • 2、泛型只能是引用数据类型
  • 如果是基本数据类型,则使用它的包装类
public class GenericDemo {
  public static void main(String[] args) {
//    Collection coll = new ArrayList();
//    coll.add(new Student("我要去输液了",38));
//    coll.add(new Student("要输什么液",20));
//    coll.add(new Teacher("想你的夜",30));
//    coll.add("哈哈哈~~平衡了");
//    //获取迭代器对象
//    Iterator it = coll.iterator();
//    while(it.hasNext()) {
//      Student stu = (Student) it.next();
//      stu.play();
//    }
    
//    Collection<Student> coll = new ArrayList<>();
//    coll.add(new Student("我要去输液了",38));
//    //coll.add("");   不能添加其他类型的元素
//    coll.add(new Student("我要去输液了",38));
//    //获取迭代器对象
//    Iterator<Student> it = coll.iterator();
//    while(it.hasNext()) {
//      Student stu = it.next();
//      stu.play();
//    }
    
//    Collection<Person> coll = new ArrayList<Person>();
//    coll.add(new Student("我要去输液了",38));
    
//    Collection<Integer> coll = new ArrayList<Integer>();
  }
}
class Person{
}
class Teacher extends Person{
  String name;
  int age;
  public Teacher() {
  } 
  public Teacher(String name, int age) {
    super();
    this.name = name;
    this.age = age;
  } 
}
class Student extends Person{
  String name;
  int age;
  public Student() {
  } 
  public Student(String name, int age) {
    super();
    this.name = name;
    this.age = age;
  } 
  public void play() {
    System.out.println("就是玩儿");
  }
}

14.5 ArrayList类

14.5.1 常用方法
  • add(innt index, E element)
  • remove(int index)
  • set(int index, E element)
  • get(int index)
  • subList(int beginIndex,int endIndex)
  • list.listIterator();
package com.qf.demo02;

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

public class ArrayListDemo {
  public static void main(String[] args) {
    List<String> list = new ArrayList<String>();
    //List集合相对于Collection集合多了一些关于下标操作的方法
    
    //List集合的常用方法
    list.add("jack");
    list.add("rose");
    list.add("cxk");
    list.add("尼古拉斯");
    System.out.println(list);
    System.out.println("======================================");
    //在集合指定下标位置上添加元素      add(index, element)
    list.add(0, "李雷");
    list.add(3, "韩梅梅");
    list.add(6, "亚洲舞王");
    //list.add(10, "赵四");  下标范围:0~size
    System.out.println(list);
    System.out.println("======================================");
    //清空集合中所有的元素  clear()
    //list.clear();
    //System.out.println(list);
    System.out.println("======================================");
    
    //返回元素在集合中的下标,如果不存在返回-1
    System.out.println(list.indexOf("cxk"));
    //返回元素在集合中的下标(找到集合中最后一个相同元素),如果不存在返回-1
    System.out.println(list.lastIndexOf("cxk"));
    
    System.out.println("======================================");
    //移除集合中指定下标位置上的元素    下标范围:0 ~ size-1
    list.remove(0);
    System.out.println(list);
    
    System.out.println("======================================");
    //修改集合中指定下标位置上的元素     下标范围:0 ~ size-1
    list.set(1, "李雷");
    System.out.println(list);
    
    System.out.println("======================================");
    //截取集合中指定下标开始到结束位置上的元素
    List<String> list1 = list.subList(2, 5);
    System.out.println("list1----》"+list1);
    
    System.out.println("======================================");
    //获取指定下标位置上的元素
    System.out.println(list.get(0));
    
    /**
     * List集合遍历的三种方式:
     *   1、迭代器
     *   2、for循环
     *   3、foreach循环(增强for循环)  可以遍历数组和集合
     *   
     *   语法:
     *    for(元素的类型    变量  : 数组|集合){ //变量就表示遍历出来的元素
     *   
     *      }
     */
    System.out.println("===================迭代器遍历===================");
    Iterator<String> it = list.iterator();
    while(it.hasNext()) {
      System.out.println(it.next());
    }
    System.out.println("===================for循环遍历===================");
    for (int i = 0; i < list.size() ; i++) {
      System.out.println(list.get(i));
    }
    System.out.println("===================foreach循环遍历===================");
    for(String s : list) {
      System.out.println(s);
    }
    
    System.out.println("=================list集合的迭代器=====================");
    ListIterator<String> li = list.listIterator();
//    while(li.hasNext()) {
//      System.out.println(li.next());
//    }
//    
//    while(li.hasPrevious()) {
//      System.out.println(li.previous());
//    }
        
    while(li.hasNext()) {
      li.add("hehe");
      System.out.println(li.next());
    }
    System.out.println("--------------");
    while(li.hasPrevious()) {
      System.out.println(li.previous());
    }
  }
}
14.5.2 实现原理

ArrayList其底层实现使用数组

实现原理

image.png

14.6 LinkedList类

14.6.1 常用方法

常用的方法与ArrayList一致。自己独有一些向首尾添加移除等方法(可以模拟对列、堆栈等数据结构)

package com.qf.demo02;

import java.util.LinkedList;

public class LinkedListDemo {
  public static void main(String[] args) {
    //创建LinkedList对象
    LinkedList<String> list = new LinkedList<String>();
    list.add("jack");
    list.add("rose");
    list.add("cxk");
    list.add("李雷");
    list.add("韩梅梅");
    list.add(1, "马冬梅");
    System.out.println(list);
    
    list.addFirst("尼古拉斯");
    list.addLast("亚洲舞王");
    System.out.println(list);
    
    System.out.println("================================================");
    System.out.println(list.getFirst());
    System.out.println(list.getLast());
    System.out.println(list.get(3));
    
    
    System.out.println("================模拟栈结构==================");
    LinkedList<String> list1 = new LinkedList<String>();
    list1.push("aa");
    list1.push("bb");
    System.out.println(list1.pop());
    System.out.println(list1.pop());
    
    System.out.println("================模拟对列结构==================");
    LinkedList<String> list2 = new LinkedList<String>();
    //向对列的尾部添加元素
    list2.offer("哈哈");
    list2.offer("呵呵");
    list2.offer("嘻嘻");
    list2.offer("hiahia");
    //获取并移除对列的头部的元素
    System.out.println(list2.poll());
    System.out.println(list2.poll());
    System.out.println(list2.poll());
    System.out.println(list2.poll());
    //获取但不移除对列的头部的元素
    //System.out.println(list2.element());
    //获取但不移除对列的头部的元素
    //System.out.println(list2.peek());
    System.out.println(list2);
    
    //LinkedList集合三种遍历方式
  }
}


14.6.2 LinkedList实现原理
实现原理

image.png

14.6.3 堆栈和队列结构
堆栈和队列结构

image.png

14.7 Vector类

14.7.1 常用方法

ArrayList的方法基本一致

public class VectorDemo {
  public static void main(String[] args) {
    Vector<String> vector = new Vector<String>();
    vector.add("aa");
    System.out.println(vector);
    /**
     * ArrayList、LinkedList、Vector的区别
     * 
     * ArrayList和Vector底层使用数组实现(增删慢、查询快)
     *   ArrayList是当添加元素的时候,才会扩容数组,默认长度为10
     *   Vector是当创建对象的是,就创建长度为10的数组
     *   ArrayList线程不安全,效率高
     *   Vector是线程安全的,效率低
     *   
     * LinkedList底层使用双向链表实现(增删快、查询慢)
     */
  } 
}
14.7.2 实现原理

ArrayList的底层一致,使用数组实现

14.7.3 常见面试问题

ArrayListLinkedListVector的区别:

ArrayList和Vector底层使用数组实现(增删慢、查询快)

  • ArrayList是当添加元素的时候,才会扩容数组,默认长度为10, Vector是当创建对象的是,就创建长度为10的数组
  • ArrayList线程不安全,效率高 Vector是线程安全的,效率低
  • LinkedList底层使用双向链表实现(增删快、查询慢)

14.8 HashSet类

14.8.1 HashSet基本使用

常用方法与Collection接口中定义的方法一致

特点:

  • 无序 (插入顺序)
  • 无下标
  • 不可重复
HashSet<String> set = new HashSet<String>();
set.add("jack");
set.add("rose");
set.add("cxk");
set.add("jack");
System.out.println(set);
14.8.2 HashSet 去重原理

HashSet底层去重:

首先会比较两个对象的hashCode的值,如果hashCode值不一样,则直接认为两个对象是不同的对象,如果HashCode值一样,那么就会比较两个方法的equals方法, 如果equals方法返回false,则表示两个对象是不同的对象,如果equals方法返回true,则表示两个对象是相同的对象,则不会向HashSet中添加

总之:HashSet确定对象是否重复,是先判断hashcode再判断equals,两者都相等则认为是相同对象

HashSet<User> userSet = new HashSet<User>();
User cxk = new User("cxk", "123");
userSet.add(cxk);
userSet.add(new User("jack", "456"));
userSet.add(new User("王校长", "输液..."));
userSet.add(new User("jack", "456")); // 相同对象无法插入
userSet.add(cxk);// 相同对象无法插入

重写hashCodeequals方法

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((password == null) ? 0 : password.hashCode());
    result = prime * result + ((username == null) ? 0 : username.hashCode());
    return result;
}
@Override
public boolean equals(Object obj) {
    //判断两个对象是否是同一个对象
    if (this == obj)
        return true;
    //判断比较的对象是否为null
    if (obj == null)
        return false;
    //getClass() 返回对象的真实(运行)类型
    if (getClass() != obj.getClass())
        return false;
    User other = (User) obj;
    if (password == null) {
        if (other.password != null)
            return false;
    } else if (!password.equals(other.password))
        return false;
    if (username == null) {
        if (other.username != null)
            return false;
    } else if (!username.equals(other.username))
        return false;
    return true;
}

14.9 LinkedHashSet类

LinkedHashSet

特点::

  • 1、有序
  • 2、无下标
  • 3、不可重复

与父类的方法一致,去重的原理,也与父类一致

public class LinkedHashSetDemo {
  public static void main(String[] args) {
    //LinkedHashSet  有序(链表维护顺序)  不能重复
    LinkedHashSet<String> set = new LinkedHashSet<>();
    set.add("jack");
    set.add("大娃");
    set.add("二娃");
    set.add("rose");
    set.add("爷爷");
    set.add("爷爷");
    for (String s : set) {
      System.out.println(s);
    }
        //1、底层实现 (LinkedHashMap)
        //2、去重原理 (与hashSet一致)
  }
}

14.10 Collections工具类

集合: 工具类(Collections)


Collections.reverse(List list)

将集合中的元素反转

Collections.shuffle(List list)

将集合中的元素随机打乱

  • Collections.sort(List list)
  • 将集合中的元素排序 (必须要实现Comparable接口)
 public class CollectionsDemo {
  public static void main(String[] args) {
    List<String> list = new ArrayList<String>();
    list.add("jack");
    list.add("大娃");
    list.add("二娃");
    list.add("rose");
    list.add("妖怪");
    list.add("蛇妖");
    list.add("蛇妖");
    System.out.println(list);
    //按照字典顺序
    Collections.sort(list);
    System.out.println(list);
    
    //将集合元素进行翻转
    Collections.reverse(list);
    System.out.println(list);
    
    //将集合中的元素进行随机打乱
    Collections.shuffle(list);
    System.out.println(list);
    
    //Arrays数组工具类      Collections集合工具类
  }
}



目录
相关文章
|
4天前
|
存储 安全 Java
Java 集合框架中的老炮与新秀:HashTable 和 HashMap 谁更胜一筹?
嗨,大家好,我是技术伙伴小米。今天通过讲故事的方式,详细介绍 Java 中 HashMap 和 HashTable 的区别。从版本、线程安全、null 值支持、性能及迭代器行为等方面对比,帮助你轻松应对面试中的经典问题。HashMap 更高效灵活,适合单线程或需手动处理线程安全的场景;HashTable 较古老,线程安全但性能不佳。现代项目推荐使用 ConcurrentHashMap。关注我的公众号“软件求生”,获取更多技术干货!
23 3
|
2月前
|
Java 数据库
在Java中使用Seata框架实现分布式事务的详细步骤
通过以上步骤,利用 Seata 框架可以实现较为简单的分布式事务处理。在实际应用中,还需要根据具体业务需求进行更详细的配置和处理。同时,要注意处理各种异常情况,以确保分布式事务的正确执行。
|
2月前
|
消息中间件 Java Kafka
在Java中实现分布式事务的常用框架和方法
总之,选择合适的分布式事务框架和方法需要综合考虑业务需求、性能、复杂度等因素。不同的框架和方法都有其特点和适用场景,需要根据具体情况进行评估和选择。同时,随着技术的不断发展,分布式事务的解决方案也在不断更新和完善,以更好地满足业务的需求。你还可以进一步深入研究和了解这些框架和方法,以便在实际应用中更好地实现分布式事务管理。
|
2月前
|
JSON Java Apache
非常实用的Http应用框架,杜绝Java Http 接口对接繁琐编程
UniHttp 是一个声明式的 HTTP 接口对接框架,帮助开发者快速对接第三方 HTTP 接口。通过 @HttpApi 注解定义接口,使用 @GetHttpInterface 和 @PostHttpInterface 等注解配置请求方法和参数。支持自定义代理逻辑、全局请求参数、错误处理和连接池配置,提高代码的内聚性和可读性。
169 3
|
21天前
|
存储 缓存 安全
Java 集合江湖:底层数据结构的大揭秘!
小米是一位热爱技术分享的程序员,本文详细解析了Java面试中常见的List、Set、Map的区别。不仅介绍了它们的基本特性和实现类,还深入探讨了各自的使用场景和面试技巧,帮助读者更好地理解和应对相关问题。
37 5
|
2月前
|
存储 缓存 安全
Java 集合框架优化:从基础到高级应用
《Java集合框架优化:从基础到高级应用》深入解析Java集合框架的核心原理与优化技巧,涵盖列表、集合、映射等常用数据结构,结合实际案例,指导开发者高效使用和优化Java集合。
44 4
|
2月前
|
开发框架 Java 关系型数据库
Java哪个框架适合开发API接口?
在快速发展的软件开发领域,API接口连接了不同的系统和服务。Java作为成熟的编程语言,其生态系统中出现了许多API开发框架。Magic-API因其独特优势和强大功能,成为Java开发者优选的API开发框架。本文将从核心优势、实际应用价值及未来展望等方面,深入探讨Magic-API为何值得选择。
66 2
|
2月前
|
前端开发 Java 数据库连接
你不可不知道的JAVA EE 框架有哪些?
本文介绍了框架的基本概念及其在编程领域的应用,强调了软件框架作为通用、可复用的软件环境的重要性。文章分析了早期Java EE开发中使用JSP+Servlet技术的弊端,包括可维护性差和代码重用性低等问题,并阐述了使用框架的优势,如提高开发效率、增强代码规范性和可维护性及提升软件性能。最后,文中详细描述了几种主流的Java EE框架,包括Spring、Spring MVC、MyBatis、Hibernate和Struts 2,这些框架通过提供强大的功能和支持,显著提升了Java EE应用的开发效率和稳定性。
108 1
|
2月前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
|
2月前
|
Java 数据库连接 API
Spring 框架的介绍(Java EE 学习笔记02)
Spring是一个由Rod Johnson开发的轻量级Java SE/EE一站式开源框架,旨在解决Java EE应用中的多种问题。它采用非侵入式设计,通过IoC和AOP技术简化了Java应用的开发流程,降低了组件间的耦合度,支持事务管理和多种框架的无缝集成,极大提升了开发效率和代码质量。Spring 5引入了响应式编程等新特性,进一步增强了框架的功能性和灵活性。
53 0