IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java集合(一) -> 正文阅读

[Java知识库]Java集合(一)

1、集合与数组存储数据概述:
  • 1.集合、数组都是对多个数据进行存储操作的结构,简称Java容器
  • 说明:此时的存储主要指的是内存层面的存储,不涉及持久化的存储(.txt,.jpg,.avi,数据库中)
2、数组存储的特点:
  • 一旦初始化,其长度就确定了。
  • 数组一旦定义了,其元素的类型就确定了。我们也就只能操作指定类型的数据了。
  • 比如:String[] arr; int[] arr1; Object[] arr3;
3、数组存储的弊端:
  • 一旦初始化了,其长度就不可修改。
  • 数组提供的方法有限,对于添加、删除、插入数据等操作,非常不便。
  • 获取数组中实际元素个数的需求,数组没有现成的属性或方法可用。
  • 数组存储数据的特点:有序、可重复。对于无序。不可重复的需求,不能满足。
4、集合存储的优点:
  • 解决数组存储数据方面的弊端。
5、单列集合框架

Collection接口:单列集合,用来存储一个一个的对象

  • List接口:存储有序的、可重复的数据。–>“动态数组”
    • Arraylist、linkedList、Vector
  • Set接口:存储无序的、不可重复的数据。高中讲的集合“集合”
    • HashSet、linkedHashSet、TreeSet
6、Collection接口的所有抽象方法
//boolean add(E e) 将元素e添加到集合中
//int size():获取集合中元素的个数
//boolean   addAll(Collection<? extends E> c) :将c集合中的元素添加到当前的集合中
//boolean   isEmpty():size == 0 判断集合是否为空
//void      clear():清空集合元素
//boolean   contains(Object o) 判断集合中是否包含o 底层使用equals方法
//boolean   containsAll(Collection<?> c) 判断集合c中的元素是否全部在当前集合中
//boolean   remove(Object o):将形参o从当前集合中移除
//boolean   removeAll(Collection<?> c)差集:把当前集合中与形参c集合共有的元素移除
//boolean   retainAll(Collection<?> c)交集:获取当前集合与集合c的交集,并返回给当前集合
//boolean   equals(Object o):判断当前集合的所有元素与形参集合所有的元素是否相同,位置对应
//int hashCode():返回当前对象的哈希值
//集合 ---> 数组:toArray()
//数组 ---> 集合:Arrays.asList()
//iterator():返回Iterator接口的实例,用于遍历集合元素。
8、Collection集合与数组间的转换

//集合 —> 数组:toArray()
Object[] obj = coll.toArray();
System.out.println(Arrays.toString(obj));
//数组 —> 集合:Arrays.asList(@NotNull T… a)
List strings = Arrays.asList(“123”, "213 ", “52”);
System.out.println(strings);

9、使用Collection集合存储对象,要求对象所属类满足:

向Collection接口的实现类的对象中添加数据obj时,要求obj所在类重写equals()方法

10、遍历Collection的方式:
Collection coll = new ArrayList();
coll.add("AA");
coll.add(123);
coll.add(new Date());
coll.add(new String("Tom"));
coll.add(new Person("Jerry",12));
//方式一 迭代
//hasNext():判读是否还有下一个元素
Iterator iterator = coll.iterator();
while (iterator.hasNext()){
   //next():①指针下移 ②将下移以后集合位置上的元素返回
   System.out.println(iterator.next());
}
//方式二: foreach
for(Object o : coll){
System.out.println(o);
}
//方式三 引用
coll.forEach(System.out::println);
11、java.utils包下定义的迭代器接口:Iterator

说明:*Iterator对象成为迭代器(设计模式的一种),主要用于遍历Collection集合中的元素
*GOF给迭代器模式的定义为:提供一种方法访问一个一个容器(container)对象中各个元素,
而又不暴露该对象的内部细节。迭代器模式,就是为容器而生。
测试:Iterator中的remove()
如果还未调用next()或在上一次调用next()方法之后已经调用了remove()方法
再调用remove()方法,都会报IllegalStateException。

12、foreach循环

说明:

  • for(集合中元素的类型 局部变量:集合或数组对象 ){
    循环体
    }
  • 代码举例
    for(Object o : coll){
    System.out.println(o);
    }
13、List接口:

存储的数据的特点:单列集合,用来存储一个一个的对象
框架:

  • Collection接口:单列集合,用来存储一个一个的对象
  • List接口:存储有序的、可重复的数据。–>“动态数组”
    • Arraylist:作为List接口的主要实现类;线程不安全的,效率高;底层使用Object[] elementData存储
    • LinkedList:对于频繁的插入、删除操作,使用此类效率比ArrayList高;底层使用双向链表存储。
    • Vector:作为List接口的古老实现类;线程安全的的,效率低;底层使用Object[] elementData存储存储
源码分析:
* ArrayList源码分析:
*  jdk7情况下:
*      *ArrayList list = new ArrayList(); //底层创建了长度是10的Object[]数组elementData
*      *list.add(123)//elementData[0] = new Integer(123);
*      *...
*      *list.add(12)//如果此次添加导致底层elementData数组容量不够,则扩容。
*      *默认情况下,扩容为原来的1.5倍,同时需要将原有数组中的数据复制到新的数组中。
*      *结论:开发中,建议使用带参的构造器:ArrayList list = new  ArrayList(int capacity)
*
*  jdk8中ArrayList的变化:
*      *ArrayList list = new ArrayList(); //底层并没有创建了长度是10的Object[]数组elementData
*      *list.add(123)//此时才创建长度是10的数组 elementData[0] = new  Integer(123);
*      *...
*      *后续的添加和扩容操作同jdk7一致
* 小结:jdk7中的ArrayList的对象的创建类似于单例模式的饿汉式,而jdk8中的ArrayList的对象
*  的创建类似于单例模式的懒汉式,延迟了数组的创建,节省了内存
*
* LinkedList的源码分析:
*      *LinkedList list = new LinkedList();//内部声明了Node类型的first和last属性,默认值为null
*      *list.add(123);//将123封装到Node中,创建了Node对象
*      *其中Node定义为:体现了LinkedList的双向链表的说法******
*      *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;                           *
*      *  }                                                *
*      *}                                                  *
*      *****************************************************
*
* Vector的源码分析
*      *jdk7和jdk8中铜鼓Vector()构造器创建对象时,底层都创建了长度为10的数组。
*      *扩容方面,默认扩容原来长度的2
常用方法:
    void add(int index,Object ele):在index位置插入ele元素
    boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加到当前集合
    int indexOf(Object obj):返回obj在集合中首次出现的位置
    int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置
    Object remove(int index):移除指定index位置的元素,并返回此元素
    Object set(int index,Object obj):设置指定index位置的元素为obj,并返回此元素
    List subList(int fromIndex,int toIndex):返回从fromIndex到toIndex位置的左闭右开区间的子集合
	   总结:
*      *增:add()/addAll()
*      *删:remove(int index)/remove(Object obj)
*      *改:set(int index,Object obj)
*      *查:get(int index)
*      *插:add(int index,Object obj)
*      *长度:size()
*      *遍历:①Iterator 迭代器方式
*            ②:增强for循环 foreach方式
*            ③:普通的循环
遍历的三种方式:
	@Test
    public void test2(){
        ArrayList list = new ArrayList();
        list.add(123);
        list.add("AA");
        list.add(true);
        list.add(new Person("Tom",12));
        //way 1:Iterator迭代器
        Iterator iterator = list.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        System.out.println("*********************");
        //way 2:foreach
        for(Object l : list){
            System.out.println(l);
        }
        System.out.println("*********************");
        //way 3:普通循环
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
    }

存储元素的要求:

添加到对象,所在的类需要重写equals()方法

面试题:Arraylist、linkedList、Vector的异同?

  • 相同:三个类都实现了List接口,存储数据的特点相同:存储有序的,可重复的数据
  • 不同:
    • Arraylist:作为List接口的主要实现类;线程不安全的,效率高;底层使用Object[] elementData存储
    • LinkedList:对于频繁的插入、删除操作,使用此类效率比ArrayList高;底层使用双向链表存储。
    • Vector:作为List接口的古老实现类;线程安全的的,效率低;底层使用Object[] elementData存储存储
[区分List当中的remove(int index)方法和remove(Object o)方法]
代码举例:
public class ListExer {
    @Test
    public void test1(){
        List list = new ArrayList();
        list.add(1);
        list.add(2);
        list.add(3);
        upDateList(list);
        System.out.println(list);
    }
    private void upDateList(List list) {
        list.remove(new Integer(2));//list.remove(2);//默认将数字2当成索引
    }
}
14、Set接口
框架:
* *  |----Collection接口:单列集合,用来存储一个一个的对象
*       |---Set接口:存储无序的、不可重复的数据。-->高中讲的集合“集合”
*          |---HashSet:作为Set接口的主要实现类;线程不安全;可以存储null值
*              |---LinkedHashSet:作为HashSet的子类;遍历其内部数据时,可以按照添加的顺序遍历
*                                  对于频繁的遍历操作,LinkedHashSet效率高于HashSet
*          |---TreeSet:可以按照添加对象的指定属性,进行排序。
* 说明:Set接口中,没有额外定义新的方法,使用的都是Collection接口中声明的方法
* 要求:向Set中添加的数据,其类一定要重写hashCode()和equals()方法,以实现对象相等规则
* 要求:重写的hashCode()和equals()尽可能保持一致(相等的对象必须具有相等的散列码)。
*  重写方法的小技巧:对象中用作equals()方法比较的Field,都应该用来计算hashCode值。

常用实现类:
一、Set:存储无序的、不可重复的数据

以HashSet为例说明:

  • 1、无序性
    无序不等于随机性
    存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数据的哈希值决定
  • 2、不可重复性
    保证添加的元素按照equals()判断是,不能反悔true。即:相同的元素只能添加一个。

二:添加元素的过程:以HashSet为例:

     我们向HashSet中添加元素a,首先调用元素a所在类的hashCode()方法,计算元素a的哈希值,
     此哈希值接着通过某种算法计算出在HashSet底层数组中的存放位置(即为:索引位置),
     判断数组此位置上是否已经有元素:
        *如果此位置上没有其他元素,则元素a添加成功。---情况1
        *如果此位置上有其他元素b(或以链表形式存在的多个元素),则比较元素a与元素b的hash值:
            如果hash值不同,则元素a添加成功 ---情况2
            如果hash值相同,进而需要调用元素a所在类的equals()方法,
                equals()返回true,则元素添加失败
                equals()返回false,则元素a添加成功。---情况3
      对于添加成功的情况2和情况2而言:元素a 与已经存在指定索引位置上数据已链表的方式存储。
      jdk7:元素a放到数组中,指向原来的元素
      jdk8:原来的元素在数组中,指向元素a
      总结:七上八下
      HashSet底层:数组+链表的结构。

三、LinkedHashSet的使用:

    LinkedHashSet作为HashSet的子类,在添加数据的同时,每个数据还维护了两个引用,
    记录此数据前一个数据和后一个数据
    优点:对于频繁的遍历操作,LinkedHashSet效率高于HashSet

四、TreeSet的使用:

      1.向TreeSet中添加数据,要求是相同类的对象。
      2.两种排序方式:自然排序 和 定制排序
      3.自然排序中,比较两个对象是否相同的标准为:compareTo()返回0,不再是equals()方法。
      4.定制排序中,比较两个对象是否相同的标准为:compare()返回0,不再是equals()方法。
		存储对象所在类的要求:要求对象所在类重写equals()和hashCode()方法

END
视频课程笔记
课程:尚硅谷JavaSE

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-11-15 15:42:36  更:2021-11-15 15:44:25 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 3:10:05-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码