集合学习笔记

Collection接口【集合】**

一、概述

集合到底是什么呢 ?

  • 集合是java中提供的一种容器,可以用来存储多个数据。

集合和数组既然都是容器,它们有啥区别呢 ?

  • 数组的长度是固定的。集合的长度是可变的。
    • int[ ] arr = new int[10];
    • Student[ ] arr = new Student[3];
    • ArrayList//
  • 数组中存储的是同一类型的元素,可以存储基本数据类型值。
  • 集合存储的都是对象。而且对象的类型可以不一致。在开发中一般当对象多的时候,使用集合进行存储。
二、集合框架

集合按照其存储结构可以分为两大类,分别是单列集合java.util.collection 和 双列集合java.util.Map
Collection,单列集合类的根接口,用于存储一系列符合某种规则的元素。它有两个重要的子接口
分别是 java.util.List 和 java.util.Set 。

其中,List的特点是元素有序、元素可重复。Set 的特点是元素无序,而且不可重复。

List接口的主要实现类有 java.util.ArrayList 和 java.util.LinkedList。

Set 接口的主要实现类有 java.util.Hashset 和 java.util.TreeSet。
通过一张图来描述整个集合类的继承体系。

在这里插入图片描述
在这里插入图片描述

三、Collection集合常用方法
boolean add(E e)//向集合中添加元素
boolean remove(E e)//删除集合中的某个元素
void clear()//清空集合所有的元素
boolean contains(E e)//判断集合中是否包含某个元素
boolean isEmpty0)//判断集合是否为空
int size()//获取集合的长度
object[] toArray()//将集合转成一个数组
Iterator<E> iterator() //返回在此 collection 的元素上进行迭代的迭代器。
四、迭代器

在程序开发中,经常需要遍历集合中的所有元素。针对这种需求,JDK专门提供了一个接口
java.util.Iterator 。Iterator接口也是Java集合中的一员,但它与collection 、Map接口有所不同,Collection接口与Map 接口主要用于存储元素,而 Iterator主要用于迭代访问(即遍历) collection 中的元素,因此 Iterator对象也被称为迭代器。想要遍历Collection集合,那么就要获取该集合迭代器完成迭代操作。

获取迭代器的方法∶

  • public Iterator iterator( ) : 获取集合对应的迭代器,用来遍历集合中的元素的。

  • 迭代的概念︰

    • 迭代 : 即Collection集合元素的通用获取方式。在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。

lterator接口的常用方法如下︰

public E next()//返回迭代的下一个元素。
public boolean hasNext()//如果仍有元素可以迭代,则返回true。
例子:
public class IteratorTest {
    public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<>();
        arrayList.add("李白");
        arrayList.add("王昭君");
        arrayList.add("韩信");
        arrayList.add("刘邦");
        // foreach 输出
        for (String s : arrayList) {
            System.out.println(s);
        }

        //迭代器 输出
        Iterator<String> iterator = arrayList.iterator();//获取一个迭代器
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
}
五、增强 for 循环

增强for循环 (也称for each循环) 是JDK1.5以后出来的一个高级for循环,专门用来遍历数组和集合的。它的内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。
格式︰
for (元素的数据类型变量 : collection集合 or 数组 ){
//写操作代码
}
它用于遍历Collection和数组。通常只进行遍历元素,不要在遍历的过程中对集合元素进行增删操作。

六、List 接口
一、概述
  1. List 接口介绍
    java.util.List 接口继承自collection接口,是单列集合的一个重要分支,习惯性地会将实现了List 接口的对象称为List集合。在List集合中允许出现重复的元素,所有的元素是以一种线性方式进行存储的,在程序中可以通过索引来访问集合中的指定元素。另外,List集合还有一个特点就是元素有序,即元素的存入顺序和取出顺序一致。
  2. List接口特点∶
    • 它是一个元素存取有序的集合。
      • 例如,存元素的顺序是11、22、33。那么集合中,元素的存储就是按照11、22、33的顺序完成的)。
    • 它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是一个道理)
    • 集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素。
二、常用方法
				/*list接口中带索引的方法(特有)*/
//将指定的元素,添加到该集合中的指定位置上。 
public void add(int index, E element)
//返回集合中指定位置的元素。
public E get( int index)
//移除列表中指定位置的元素,返回的是被移除的元素。    
public E remove(int index)
//用指定元素替换集合中指定位器的元素,返回值的更新前的元素
public E set(int index,E eLement)				
三、ArrayList

java.util.ArrayList集合数据存储的结构是数组结构。元素增删慢,查找快,由于日常开发中使用最多的功能为查询数据、遍历数据,所以ArrayList是最常用的集合。

许多程序员开发时非常随意地使用ArrayList完成任何需求,并不严谨,这种用法是不提倡的。

四、LinkedList集合

java.util.LinkedList集合数据存储的结构是链表结构。方便元素添加、删除的集合。LinkedList是一个双向链表,那么双向链表是什么样子的呢,我们用个图了解下。

在这里插入图片描述

实际开发中对一个集合元素的添加与删除经常涉及到首尾操作,而LinkedList提供了大量首尾操作的方法。这些方法我们作为了解即可:

public void addFirst(E e)//将指定元素插入此列表的开头。
public void addLast(E e)//将指定元素添加到此列表的结尾。
public E getFirst()//返回此列表的第一个元素。
public E getLast()//返回此列表的最后一个元素。
public E removeFirst()//移除并返回此列表的第一个元素。
public E removeLast()]//移除并返回此列表的最后一个元素。
public E pop()//从此列表所表示的堆栈处弹出一个元素。
public void push(E e)//将元素推入此列表所表示的堆栈。
public boolean isEmpty()//如果列表不包含元素,则返回true。

LinkedList 是 List的子类,List 中的方法 LinkedList 都是可以使用,这里就不做详细介绍,我们只需要了解LinkedList的特有方法即可。在开发时,LinkedList集合也可以作为堆栈,队列的结构使用。(了解即可)

七、Set 接口
一、概述

java.util.Set 接口和java.util.List 接口一样,同样继承自 collection 接口,它与 collection 接口中的方法基本一致,并没有对collection接口进行功能上的扩充,只是比 collection接口更加严格了。与List 接口不同的是,set 接口中元素无序,并且都会以某种规则保证存入的元素不出现重复。
set集合有多个子类,这里我们介绍其中的java.util.HashSet、java.util.LinkedHashSet 这两个集合。

tips: Set 集合取出元素的方式可以采用 : 迭代器、增强for。

简单的来说,哈希表是由数组+链表+红黑树(JDK1.8增加了红黑树部分)实现的,如下图所示 :

在这里插入图片描述
在这里插入图片描述

元素不会重复的原理:
在这里插入图片描述

二、 HashSet集合介绍
1、HashSet

java.util.HashSet是 set 接口 的 一个实现类,它所存储的元素是不可重复的,并且元素都是无序的(即存取顺序不一致)。java.util.HashSet 底层的实现其实是一个 java.util.HashMap 支持,由于我们暂时还未学习,先做了解。

HashSet 是根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存取和查找性能。保证元素唯一性的方式依赖于: hashcode 与 equals方法。

2 HashSet集合存储数据的结构(哈希表)

什么是哈希表呢?
在 JDK1.8之前,哈希表底层采用数组+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里。但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。

而 JDK1.8中,哈希表存储采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。
简单的来说,哈希表是由数组+链表+红黑树(JDK1.8增加了红黑树部分)实现的。

哈希值 :是一个十进制的整数,由系统随机给出(就是对象的地址值,是一个逻辑地址,是模拟出来得到地址,不是数据实际存储的物理地址),在object类有一个方法, 可以获取对象的哈希值 int hashcode( ) 返回 该对象的哈希码值。

hashcode方法的源码 :

public native int hashcode();//native:代表该方法调用的是本地操作系统的方法
3 、HashSet存储自定义类型元素

给HashSet中存放自定义类型元素时,需要重写对象中的 hashCode( ) 和 equals( ) 方法,建立自己的比较方式,才能保证HashSet集合中的对象唯一。

三、LinkedHashSet

我们知道 HashSet 保证元素唯一,可是元素存放进去是没有顺序的,那么我们要保证有序,怎么办呢?在HashSet下面有一个子类 java.util.LinkedHashSet,它是链表和哈希表组合的一个数据存储结构。

// 例子
public class LinkedHashsetDemo {
public static void main(string[] args) {
	Set<String> set = new LinkedHashset<String>();
    set.add( "bbb");
	set.add( "aaa" );
    set.add( "abc");
    set.add( "bbc" );
	Iterator<String> it = set.iterator( );
    while (it.hasNext()){
		system.out.println(it.next());
	   }
	}
 }
/*
结果∶
	bbb
    aaa
    abc
*/

五、Collections --集合工具类

常用功能

java.utils.collections 是集合工具类,用来对集合进行操作。

部分方法如下︰

//往集合中添加一些元素。
public static <T> boolean addAll(Collection<T> c,T... elements) 
//打乱集合顺序[随机排序]    
public static void shuffle(List<? > list)
//将集合中元素按照默认规则排序。
public static <T> void sort(List<T> list)
//将集合中元素按照指定规则排序。    
public static T> void sort(List<T> list , comparator<? super T〉)

六、Map集合

一、概述

现实生活中,我们常会看到这样的一种集合∶IP地址与主机名,身份证号与个人,系统用户名与系统用户对象等,这种一一对应的关系,就叫做映射。

Java提供了专门的集合类用来存放这种对象关系的对象,即 java.util.Map 接口。

我们通过查看Map接口描述,发现 Map接口下的集合与collection接口下的集合,它们存储数据的形式不同,如下图。
在这里插入图片描述

  • collection 中的集合,元素是孤立存在的,向集合中存储元素采用一个个元素的方式存储。
  • Map 中的集合,元素是成对存在的。每个元素由键与值两部分组成,通过键可以找对所对应的值。
  • collection 中的集合称为单列集合,Map 中的集合称为双列集合。
  • 需要注意的是,Map中的集合不能包含重复的键,值可以重复 :每个键只能对应一个值。

二、常用子类

通过查看Map接口描述,看到Map有多个子类,这里我们主要讲解常用的HashMap集合、LinkedHashMap集合。

  • HashMap<K,V>∶存储数据采用的哈希表结构,元素的存取顺序不能保证一致。由于要保证键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。
  • LinkedHashMap<K,V> : HashMap下有个子类LinkedHashMap,存储数据采用的哈希表结构+链表结构。通过链表结构可以保证元素的存取顺序一致; 通过哈希表结构可以保证的键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。
  • tips : Map接口中的集合都有两个泛型变量<K.V>,在使用时,要为两个泛型变量赋予数据类型。两个泛型变量<K,V>的数据类型可以相同,也可以不同。

三、常用方法

public Void put(K key,v value)//把指定的键与指定的值添加到Map集合中。
    /*返回值:v
        存储键值对的时候,key不重复,返回值v是null
        存储键值对的时候,key重复,会使用新的value替换map中重复的value,返回被替换的value值 */
public Void remove(object key)//把指定的键所对应的键值对元素在Map集合中删除.
    /*返回值: v
		key存在, v返回被删除的值, key不存在,v返回null */
public Void get(0bject key)//根据指定的键,在Map集合中获取对应的值。
public Set<K> keySet()//获取Map集合中所有的键,存储到Set集合中。
public Set<Map.Entry<K,v>> entrySet()//获取到 Map集合中所有的键值对对象的集合(Set集合)。
package com.lly.myMap;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * @ClassName:Maptest1
 * @创建者: LLY
 * @创建时间: 2021/4/24 22:24
 * @version: 1.0
 * @描述: Map 集合取值练习
 * * Map集合遍历的第一种方式:
 * 使用public Set<K> keySet()//获取Map集合中所有的键,存储到Set集合中。
 */
public class Maptest1 {
    public static void main(String[] args) {
        //创建Map集合对象
        Map<String,Integer> map = new HashMap<>();
        map.put("赵丽颖",168);
        map.put("杨颖", 165);
        map.put("林志玲",178);
        Set<String> keys = map.keySet();
        // 使用增强for输出
        for (String key : keys) {
            System.out.println(key+"-->"+map.get(key));
        }
        System.out.println("=====================");
        //使用迭代器输出
        Iterator<String> iterator = keys.iterator();
        while (iterator.hasNext()) {
            String next = iterator.next();
            System.out.println(next+"-->"+map.get(next));
        }
    }
}

四、public Set keySet( ) 方式取值

在这里插入图片描述

五、Entry键值对 对象 取值

我们已经知道,Map中存放的是两种对象,一种称为key(键),一种称为value(值),它们在在wap中是
一对应关系,这一对对象又称做Map 中的一个Entry(项)。Entry)将键值对的对应关系封装成了对象。即键值对对象,这样我们在遍历wap集合时,就可以从每一个键值对([Entry )对象中获取对应的键与对应的值。
既然Entry表示了一对键和值,那么也同样提供了获取对应键和对应值得方法︰

public K getKey()//获取Entry对象中的键。
public v getValue()//获取Entry对象中的值。

在Map集合中也提供了获取所有 Entry对象 的方法∶

public Set<Map.Entry<K,v>> entrySet()//获取到Map集合中所有的键值对对象的集合(Set集合)。

六、Map集合遍历键值对方式

键值对方式︰即通过集合中每个键值对(Entry)对象,获取键值对(Entry)对象中的键与值。
操作步骤与图解︰

  1. 获取Map集合中,所有的键值对(Entry)对象,以Set集合形式返回。方法提示: entrySet() 。
  2. 遍历包含键值对(Entry)对象的Set集合,得到每一个键值对(Entry)对象。
  3. 通过键值对(Entry)对象,获取Entry对象中的键与值 。方法提示: getkey() getvalue()

在这里插入图片描述

package com.lly.myMap;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * @ClassName:Maptest
 * @创建者: LLY
 * @创建时间: 2021/4/24 22:13
 * @version: 1.0
 * @描述: Map 集合取值练习
 * ----------------------------------
 * Map集合遍历的第二种方式:使用Entry对象遍历
 * Map集合中的方法:
 * set<Map.Entry<K,v>> entrySet()返回此映射中包含的映射关系的set视图。
 * 实现步骤:
 * 1.使用Map集合中的方法entrySet( ) ,把Map集合中多个Entry对象取出来,存储到一个set集合中
 * 2.遍历set集合,获取每一个Entry对象
 * 3.使用Entry对象中的方法getKey ()和 getValue(获取键与值
 */
public class Maptest {
    public static void main(String[] args) {
        //创建Map集合对象
        Map<String,Integer> map = new HashMap<>();
        map.put("赵丽颖",168);
        map.put("杨颖", 165);
        map.put("林志玲",178);
        Set<Map.Entry<String, Integer>> entries = map.entrySet();
        // 使用增强for输出
        for (Map.Entry<String, Integer> entry : entries) {
            System.out.println(entry.getKey()+"-->"+entry.getValue());
        }
        System.out.println("=====================");
        //使用迭代器输出
        Iterator<Map.Entry<String, Integer>> iterator = entries.iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Integer> next = iterator.next();
            String key = next.getKey();
            Integer value = next.getValue();
            System.out.println(key+"-->"+value);
        }
    }
}

七、存储自定义类型的变量

HashMap存储自定义类型键值Map集合保证key是唯一的 。
即: 作为key的元素,必须重写hashcode方法和equals方法,以保证key唯一。

八、 LinkedHashMap

我们知道HashMap保证成对元素唯一,并且查询速度很快,可是成对元素存放进去是没有顺序的,那么我们要保证有序,还要速度快怎么办呢?
在HashMap下面有一个子类LinkedHashMap,它是 链表和哈希表 组合 的一个数据存储结构。

九、Hashtable

java.util.Hashtable<K,V>集合 implements Map<K,V>接口
Hashtable : 底层也是一个哈希表,是一个线程安全的集合,是单线程集合 , 速度慢

HashMap : 底层是一个哈希表,是一个线程不安全的集合,是多线程的集合, 速度快HashMap集合

  • (之前学的所有的集合) : 可以存储null 值, null 键。
  • HashtabLe集合,不能存储 null值, null键。

Hashtable和vector集合一样,在 jd k1.2版本之后被更先进的集合(HashMap , ArrayList)取代了

Hashtable的子类 Properties 依然活跃在历史舞台 , Properties集合是一个唯—和Io流相结合的集合

十、补充知识点

  1. JDK9对集合添加的优化

    • 通常,我们在代码中创建一个集合(例如,List或Set ),并直接用一些元素填充它。实例化集合,几个add方法调用,使得代码重复。

    • public class Demo01 {
          public static void main( String[] args) {
              List<String> list = new ArrayList<>();
              list.add( "abc" );
              list.add("def" );
              list.add("ghi");
              system.out.println(list);
      	}
      }
      
    • JDK9 的新特性 :

      • list接口 , set接口 , Map接口 : 里边增加了一个静态的方法 of , 可以给集合一次性添加多个元素
    • static List of (E… elements)

    • 使用前提:

      • 当集合中存储的元素的个数已经确定了,不在改变时使用
    • 注意:

      • of方法只适用于List接口, set接口,Map接口,不适用于接口的实现类
      • of方法的返回值是一个不能改变的集合,集合不能再使用add,put方法添加元素,会抛出异常.
      • Set接口 和 Map接口 在调用 of方法 的时候,不能有重复的元素,否则会抛出异常
    • public static void main(String[] args) {
          List<string> list = List.of( "a""b", "a","c""d"');
          System.out.println( list );//[a, b, a, c, d]
          //list.add( "w"); //UnsupportedoperationException:不支持操作异常
          //Set<String〉 set = Set.of("a" " "b", " a",“c" “"d");
          //TLlegaLArgumentException :非法参数异常,有重复的元素
          set<string> set = set.of( "a""b","c", "d");
          system.out.println(set);
          //set.add ( "w" ) ; // UnsuppertedoperationException:不支持操作异常
          //Map<String,Integen〉 map = Map.of("张三",18,“李四",19,“王五",20,"张三",19);/ll/ILlegaLArgumentExcepti
         Map<String,Integer> map = Map.of(k1:"张三"18,"李四"19,"王五"20);
          system.out.printin(map);//i王五=20,李四=19,张三=18}
          map.put("赵四", 30); //Unsupported0perationException:不支持操作异常
        }
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值