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集合工具类
  }
}



目录
相关文章
|
5天前
|
存储 安全 Java
Java——String类详解
String 是 Java 中的一个类,用于表示字符串,属于引用数据类型。字符串可以通过多种方式定义,如直接赋值、创建对象、传入 char 或 byte 类型数组。直接赋值会将字符串存储在串池中,复用相同的字符串以节省内存。String 类提供了丰富的方法,如比较(equals() 和 compareTo())、查找(charAt() 和 indexOf())、转换(valueOf() 和 format())、拆分(split())和截取(substring())。此外,还介绍了 StringBuilder 和 StringJoiner 类,前者用于高效拼接字符串,后者用于按指定格式拼接字符串
11 1
Java——String类详解
|
2天前
|
Java 开发者
Java Character 类详解
Java中的`Character`类是`java.lang`包的一部分,用于将基本类型`char`封装为对象,并提供了丰富的静态方法来处理字符,如类型判断、大小写转换等。
|
2天前
|
安全 Java
Java StringBuffer 和 StringBuilder 类详解
在 Java 中,`StringBuffer` 和 `StringBuilder` 用于操作可变字符串,支持拼接、插入、删除等功能。两者的主要区别在于线程安全性和性能:`StringBuffer` 线程安全但较慢,适用于多线程环境;`StringBuilder` 非线程安全但更快,适合单线程环境。选择合适的类取决于具体的应用场景和性能需求。通常,在不需要线程安全的情况下,推荐使用 `StringBuilder` 以获得更好的性能。
|
2天前
|
Java 索引
Java String 类详解
Java 中的 `String` 类用于表示不可变的字符序列,是 Java 标准库 `java.lang` 包的一部分。字符串对象一旦创建,其内容不可更改,修改会生成新对象。
|
6天前
|
Java
Java Character 类详解
`Character` 类是 Java 中的一个封装类,位于 `java.lang` 包中,主要用于处理单个字符。它是一个最终类,提供了多种静态方法来检查和操作字符属性,如判断字符是否为字母、数字或空格,以及转换字符的大小写等。此外,`Character` 类还支持自动装箱和拆箱,简化了 `char` 和 `Character` 之间的转换。以下是一些示例代码,展示了如何使用 `Character` 类的方法来检查字符属性和执行字符转换。掌握 `Character` 类的用法有助于更高效地处理字符数据。
|
SQL Java 数据库连接
Java面试题日积月累(SSM框架面试题22道)
Java面试题日积月累(SSM框架面试题22道)
75 0
|
2月前
|
设计模式 存储 安全
Java面试题:设计一个线程安全的单例类并解释其内存占用情况?使用Java多线程工具类实现一个高效的线程池,并解释其背后的原理。结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
Java面试题:设计一个线程安全的单例类并解释其内存占用情况?使用Java多线程工具类实现一个高效的线程池,并解释其背后的原理。结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
43 1
|
2月前
|
SQL Java 数据库连接
Java面试题:简述ORM框架(如Hibernate、MyBatis)的工作原理及其优缺点。
Java面试题:简述ORM框架(如Hibernate、MyBatis)的工作原理及其优缺点。
47 0
|
2月前
|
存储 安全 Java
Java面试题:请解释Java中的泛型集合框架?以及泛型的经典应用案例
Java面试题:请解释Java中的泛型集合框架?以及泛型的经典应用案例
34 0
|
2月前
|
设计模式 存储 缓存
Java面试题:结合建造者模式与内存优化,设计一个可扩展的高性能对象创建框架?利用多线程工具类与并发框架,实现一个高并发的分布式任务调度系统?设计一个高性能的实时事件通知系统
Java面试题:结合建造者模式与内存优化,设计一个可扩展的高性能对象创建框架?利用多线程工具类与并发框架,实现一个高并发的分布式任务调度系统?设计一个高性能的实时事件通知系统
42 0