zoukankan      html  css  js  c++  java
  • java.集合

    集合框架概述

    面向对象语言对事物的体现都是一对象的形式,为方便对多个对象的操作,就要对对象进行存储。另一方面,使用Array存储对象方面具有一些弊端,而Java集合就像一种容器,可以动态的把多个对象的应用放入容器中
    

    数组再内存存储方面的特点
    数组初始化以后,长度就确定了
    数组声明的类型,就决定了进行元素初始化的类型
    数组在存储数据方面的弊端
    数组初始化以后,长度就不可变了,不便于扩展
    数组中提供的属性和方法少,不便于进行添加、删除、插入等操作,且效率不高。同时无法直接获取存储元素的个数
    数组存储的数据是有序的、可以重复的

    Java集合类可以用于存储数量不等的多个对象,还可以用于保存具有映射关系的关联数组

    集合的两种体系

    Collection接口

    Collection接口是List、Set和Queue接口的父接口,该接口里定义的方法既可用于操作Set集合,也可用于操作List和Queue集合
    JDK不提供此接口的任何形式实现,而是提供风积体的子接口(如:Set和List)实现
    在Java5之前,Java集合会丢失容器中所有对象的数据类型,把所有对象都当初Object类型除了;从JDK5.0增加了泛型以后,Java集合可以记住容器中对象的数据类型
    

    Collection接口方法
    Collection是所有单列集合的父接口,因此在Collection中定义了单列集合(List和Set)通用的一些方法,这些方法可用于操作所有的单列集合。方法如下:

    • public boolean add(E e): 把给定的对象添加到当前集合中
    • public void clear() :清空集合中所有的元素
    • public boolean remove(E e): 把给定的对象在当前集合中删除
    • public boolean contains(E e): 判断当前集合中是否包含给定的对象
    • public boolean isEmpty(): 判断当前集合是否为空
    • public int size(): 返回集合中元素的个数
    • public Object[] toArray(): 把集合中的元素,存储到数组中
    import java.util.ArrayList;
    import java.util.Collection;
    
    public class Demo1Collection {
        public static void main(String[] args) {
             // 创建集合对象 
        	// 使用多态形式
        	Collection<String> coll = new ArrayList<String>();
            
        	// 使用方法
        	// 添加功能  boolean  add(String s)
        	coll.add("小李广");
        	coll.add("扫地僧");
        	coll.add("石破天");
        	System.out.println(coll);
    
        	// boolean contains(E e) 判断o是否在集合中存在
        	System.out.println("判断  扫地僧 是否在集合中"+coll.contains("扫地僧"));
    
        	//boolean remove(E e) 删除在集合中的o元素
        	System.out.println("删除石破天:"+coll.remove("石破天"));
        	System.out.println("操作之后集合中元素:"+coll);
        	
        	// size() 集合中有几个元素
            System.out.println("集合中有"+coll.size()+"个元素");
    
    	// Object[] toArray()转换成一个Object数组
        	Object[] objects = coll.toArray();
        	// 遍历数组
        	for (int i = 0; i < objects.length; i++) {
    			System.out.println(objects[i]);
                }
    
    		
            // void  clear() 清空集合
            coll.clear();
            System.out.println("集合中内容为:"+coll);
            // boolean  isEmpty()  判断是否为空
            System.out.println(coll.isEmpty());  	
    	}
    }
    

    迭代器(Iterator)

    1.Iterator对象称为迭代器(设计模式的一种),主要用于遍历Collection集合中的元素
    2.GOF给迭代器模式的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。迭代器模式,就是为容器而生。
    3.Clooection接口继承了java.lang.Iterable接口,该接口有一个iterator()方法,那么所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象
    4.Iterator仅用于遍历集合,Iterator本身并不提供承装对象的能力。如果需要创建Iterator对象,则必须有一个被迭代的集合
    5.集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前
    

    迭代器(Iterator)的方法
    Java中的Iterator功能比较简单,并且只能单向移动:
    ①使用方法Iterrator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:Iterator()方法时java.lang.
    ②使用next()获得序列中的下一个元素
    ③使用hasNext()检查列表中是否还有元素
    ④使用remove()将迭代器新返回的元素删除

    Iterator的接口定义:

    public interface Iterator{
        boolean hasNext();
        Object next();
        void remove;
    }
    

    迭代器(Iterator)应用

    public class IteratorDemo {
      	public static void main(String[] args) {
            // 使用多态方式 创建对象
            Collection<String> coll = new ArrayList<String>();
    
            // 添加元素到集合
            coll.add("串串星人");
            coll.add("吐槽星人");
            coll.add("汪星人");
            //遍历
            //使用迭代器 遍历   每个集合对象都有自己的迭代器
            Iterator<String> it = coll.iterator();
            //  泛型指的是 迭代出 元素的数据类型
            while(it.hasNext()){ //判断是否有迭代元素
                String s = it.next();//获取迭代出的元素
                System.out.println(s);
            }
      	}
    }
    

    注意:

        iterator可以删除集合的元素,但是是遍历过程中通过迭代器对象的remove方法,不是集合对象remove方法
        如果还未调用next()或在上一次调用next方法之后已经调用remove方法,再调用remove都会报
    IllegalStateException。
    
    

    增强For循环(for each)

    增强for循环(也称for each循环)是**JDK1.5**以后出来的一个高级for循环,专门用来遍历数组和集合的。它的内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。
    

    格式:

    for(元素的数据类型  变量 : Collection集合or数组){ 
      	//写操作代码
    }
    //它用于遍历Collection和数组。通常只进行遍历元素,不要在遍历的过程中对集合元素进行增删操作。
    

    练习:遍历数组

    public class NBForDemo1 {
        public static void main(String[] args) {
    		int[] arr = {3,5,6,87};
           	//使用增强for遍历数组
    		for(int a : arr){//a代表数组中的每个元素
    			System.out.println(a);
    		}
    	}
    }
    

    练习:遍历集合

    public class NBFor {
        public static void main(String[] args) {        
        	Collection<String> coll = new ArrayList<String>();
        	coll.add("小河神");
        	coll.add("老河神");
        	coll.add("神婆");
        	//使用增强for遍历
        	for(String s :coll){//接收变量s代表 代表被遍历到的集合元素
        		System.out.println(s);
        	}
    	}
    }
    

    > tips: 新for循环必须有被遍历的目标。目标只能是Collection或者是数组。新式for仅仅作为遍历操作出现。

    Collection子接口之一:List接口

    List集合类中元素有序、且可重复,集合中的每个元素都有其对应的顺序索引
    List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素
    JDK API中List接口的实现类常用的又:ArrayList、LinkedList和Vector
    

    List接口方法

    void add(int index, Objec ele) : 在index位置插入ele元素
    boolean addAll(int index, Collection eles) : 从index位置开始将eles中的所有元素添加进来
    Object get(int index) : 获取指定index位置的元素
    int indexOf(Object obj) : 返回obj在集合中首次出现的位置
    int lastIndexOf(Object obj) : 返回obj在当前集合中末次出现的位置
    Object remove(int index) : 移除指定index位置的元素,并返回此元素
    Object set(int index, Object ele) : 设置指定index位置的元素为ele
    List subList(int fromIndex, int toIndex) : 返回从fromIndex到toIndex位置的子集合

    List实现类ArrayList

    ArrayList是List接口的典型实现类、主要实现类
    本质上,ArrayList是对象引用的一个“变长”数组
    ArrayList是JDK1.8之前与之后的实现区别
        JDK1.7:ArrayList是直接创建一个初始容量为10的数组
        JDK1.8:ArrayList一开始创建一个长度为0的数组,当添加一个元素时再创建一个初始容量为哦10的数组
    Arrays.asList()方法返回的List集合,既不是ArrayList实例,也不是Vector实例。Arrays.asList()返回值是一个固定长度的List集合
    

    List实现类LinkedList

    对于频繁插入或删除元素的操作,建议使用LinkedList类,效率较高
    

    新增方法
    void addFrist(Object obj)
    void addLast(Object obj)
    Object getFirst()
    Object getLast()
    Object removeFirst()
    Object RemoverLast

    LinkedList:双向链表,内部没有声明数组,而是定义了Node类型的first和last,用于记录首末元素。同时定义内部类Node,作为LinkedList中保存数据的基本结构。Node除了保存数据,还定义了两个变量:
    prev变量记录前一个元素的位置
    next变量记录后一个元素的位置

    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;
        }
    }
    

    List实现类Vector

    Vector是一个古老的集合,JDK1.0就有了,大多数操作与ArrayList相同,区别之处在于Vector是线程安全的
    在各种list中,最好把ArrayList作为缺省选择。当插入、删除频繁时,使用LinkedList;Vector总是比ArrayList慢,所以尽量避免使用。
    

    新增方法
    void addElement(Object Obj)
    void insertElementAt(Object obj,int index)
    void setElementAt(Object obj,int index)
    void removeElement(Object obj)
    void removeAllElements()

    ArrayList和LinkedList的异同

    二者都是线程不安全的,相比于线程安全的Vector,执行效率高
    此外,ArrayList是实现了基于动态数组的数组结构,LinkedList基于链表的数据结构。对于随机访问get和set,ArrayList觉得由于LinkedList,
    应为Linked要移动指针。对于新增和删除操作add(特指插入)和remove,LinkedList比较占优势,因为ArrayList要移动数据
    

    ArrayList和Vector的区别

    Vector和ArrayList几乎是完全相同的,唯一的区别在于Vector是同步类(synchronized),属于强同步类。因此开销就比ArrayList要大,访问要慢。
    正常情况下,大多数的Java程序员使用ArrayList而不是Vector,因为同步完全可以由程序员自己来控制。Vector每次扩容请求其大小的2倍空间,而ArrayList是1.5倍空间。Vector还有一个子类Stack。
    

    Collection子接口之二:Set接口

    Set集合不允许包含相同的元素,如果试把两个相同的元素加入同一个Set集合中,则添加操作失败
    Set判断两个对象是否相同不是使用==运算符,而是根据equals()方法
    

    Set实现类之一:HashSet

    HashSet是Set接口的典型实现,大多数时候使用Set集合时都使用这个实现类
    HashSet按Hash算法来存储集合中的元素,因此具有很好的存取、查找、删除性能
    

    HashSet具有以下特点:

        不能保证元素的排列顺序
        HashSet不是线程安全的
        集合元素可以是null
    

    HashSet集合判断两个元素相等的标准:

    两个对象通过hashCode()方法比较相等,并且两个对象的equals()方法返回值也相等
    
    对于存放Set容器中的对象,对应的类一定要从重写equals()和hashCode(Object obj)方法,以实现对象相等规则。即:”相等的对象必须具有相等的散列码“。
    

    向HashSet中添加元素的过程:
    当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据hashCode值,通过某种散列函数决定该对象在HashSet底层数组中的存储位置。(这个散列函数会与底层数组的长度相计算得到在数组中的下标,并且这种散列函数计算还尽可能保证能均匀存储元素,越是散列分布,改散列函数设计的越好)

    如果两个元素的hashCode()值相等,会再继续调用equals方法,如果equals方法结果为true,添加失败;如果为false,那么会保存该元素,但是该数组的位置已经有元素了,那么会通过链表的方式继续链接。

    如果两个元素的equals()方法返回true,那么它们的hashCode()返回值不相等,hashSet将会把它们存储在不同的位置,但依然可以添加成功。

    重写hashCode()方法的基本原则
    在程序运行时,同一个对象多次调用hashCode()方法应该返回相同的值
    当两个对象的equals()方法比较返回true时,这两个对象的hashCode()方法的返回值也应相等
    对象中用作equals()方法比较Field,都应该用来计算hashCode值
    ** 重写equals()方法的基本原则**

    以自定义的Customer类为例,何时需要重写equals()?

        当一个类有自己特有的“逻辑相等”概念,当改写equals()的时候,总是
    要改写hashCode(),根据一个类的equals方法(改写后),两个截然不
    同的实例有可能在逻辑上是相等的,但是,根据Object.hashCode()方法,
    它们仅仅是两个对象。
        因此,违反了“相等的对象必须具有相等的散列码”。
        结论:复写equals方法的时候一般都需要同时复写hashCode方法。通
    常参与计算hashCode的对象的属性也应该参与到equals()中进行计算。
    

    Set实现类之二:LinkedHashSet

    LinkedHashSet 是 HashSet 的子类
    LinkedHashSet 根据元素的 hashCode 值来决定元素的存储位置,
    但它同时使用双向链表维护元素的次序,这使得元素看起来是以插入顺序保存的。
    LinkedHashSet插入性能略低于 HashSet,但在迭代访问 Set 里的全部元素时有很好的性能。
    LinkedHashSet 不允许集合元素重复。
    

  • 相关阅读:
    Eureka的集群配置
    spring-cloud_Eureka服务注册与发现
    ADB常用命令
    教你如何修改Python的pip源镜像
    【vscode】【python】自定义代码自动补全
    【docker】删除docker中的运行日志
    MVC页面上多个提交按钮提交到不同的Action
    MongoDB在windows服务器安装部署及远程连接MongoDB
    sql如果存在就修改不存在就新增
    c#序列化和反系列化json与类型对象转换
  • 原文地址:https://www.cnblogs.com/youngleesin/p/13461966.html
Copyright © 2011-2022 走看看