常用集合类
Posted Al_tair
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了常用集合类相关的知识,希望对你有一定的参考价值。
常用集合类
大家好呀!我是小笙!我学习了韩顺平老师的类和对象的知识,收获颇丰!现在来和大家分享笔记!
集合类
集合框架体系
Collection接口框架
补充框架图
Map接口框架
补充框架图
Collection接口
Collection 实现 Iterable接口 : public interface Collection extends Iterable
遍历方式
遍历方式-迭代器
Iterator接口 又称为 迭代器,主要用于遍历Collcection集合中的元素
所有实现了Collection接口的集合类都有一个Iterator()方法,用来返回一个迭代器
迭代器方法
变量和类型 | 方法 | 描述 |
---|---|---|
default void | forEachRemaining(Consumer<? super E> action) | 对每个剩余元素执行给定操作,直到处理完所有元素或操作引发异常。 |
boolean | hasNext() | 如果迭代具有更多元素,则返回 true 。 |
E | next() | 返回迭代中的下一个元素。 |
default void | remove() | 从底层集合中移除此迭代器返回的最后一个元素(可选操作)。 |
// Iterator方法的使用实例
public class Iterator01
public static void main(String[] args)
List list = new ArrayList();
list.add(new Book("三国演义",10));
list.add(new Book("水浒传",20));
list.add(new Book("西游记",15));
Iterator iterator = list.iterator();
while(iterator.hasNext())
System.out.println(iterator.next());
// 退出循环之后,迭代器指向最后一个元素
// iterator.next(); // 抛出异常 NoSuchElementException
// 需要重置迭代器 iterator = list.iterator();
static class Book
private String name;
private int price;
public Book(String name, int price)
this.name = name;
this.price = price;
@Override
public String toString()
return "Book" +
"name='" + name + '\\'' +
", price=" + price +
'';
遍历方式-for增强
特点:只能用于遍历集合和数组(简化版迭代器)
基本语法:
for(元素类型 元素名:集合名或数组名)
// 访问元素
实例
public class ForS
public static void main(String[] args)
List list = new ArrayList();
list.add(new Toy("猛虎王",10));
list.add(new Toy("霹雳火",20));
list.add(new Toy("洛洛",15));
// 增强for 本质仍然是迭代器
// 集合
for (Object b:list)
System.out.println(b.toString());
// 数组
int[] num = 2,4,5,6;
for (int n:num
)
System.out.println(n+" ");
static class Toy
private String name;
private int price;
public Toy(String name, int price)
this.name = name;
this.price = price;
@Override
public String toString()
return "Toy" +
"name='" + name + '\\'' +
", price=" + price +
'';
// debug 跳转 底层也是迭代器
// 跳转1
public Iterator<E> iterator()
return new Itr();
// 跳转2
public boolean hasNext()
return cursor != size;
// 跳转3
public E next() ......等等
遍历方式-普通for循环
public static void main(String[] args)
List list = new ArrayList();
list.add("张三丰");
list.add("秦天柱");
for (int i = 0; i < list.size(); i++)
System.out.println(list.get(i));
Collection接口特征
- 可以实现存放多个元素,每个元素可以是Object类
- 没有直接实现的子类,都是通过它的子接口Set和List来实现的
Collection的常用方法
List list = new ArrayList();
// add 添加单个元素
list.add("lns");
list.add(520); // 自动装箱 new Integer(520)
list.add("zlr");
System.out.println(list.toString()); // [lns, 520, zlr]
/*
* 父类AbstractCollection: toString方法
* public String toString()
* Iterator<E> it = iterator(); // 创建迭代器进行遍历该集合
* if (! it.hasNext())
* return "[]";
*
* StringBuilder sb = new StringBuilder();
* sb.append('[');
* for (;;)
* E e = it.next();
* sb.append(e == this ? "(this Collection)" : e);
* if (! it.hasNext())
* return sb.append(']').toString();
* sb.append(',').append(' ');
*
*
*/
// remove 删除指定元素
list.remove(1); // 等价于 list.remove(520);
System.out.println(list); // [lns, zlr]
// contains 查找元素是否存在
System.out.println(list.contains("lns")); // true
// size 获取元素个数
System.out.println(list.size()); // 2
// isEmpty 判读是否为空
System.out.println(list.isEmpty()); // false
// clear 清空
list.clear();
System.out.println(list); // []
// addAll 添加多个元素
List list2 = new ArrayList();
list2.add("lns");
list2.add("love");
list2.add("zlr");
list.addAll(list2);
System.out.println(list); // [lns, love, zlr]
// containsAll 查找多个元素是否存在
System.out.println(list.containsAll(list2)); // true
// removeAll 删除多个元素
list.add("!");
list.removeAll(list2);
System.out.println(list); // [!]
List接口
Collection接口的子接口 (队列数据结构)
特点
- List集合类元素顺序有序,且可以重复
- List集合类中的每个元素都有其对应的顺序索引
// List集合类元素顺序有序,且可以重复
List list = new ArrayList();
list.add("das");
list.add("tom");
list.add("tom");
System.out.println(list); // [das, tom, tom]
// List集合类中的每个元素都有其对应的顺序索引
System.out.println(list.get(0)); // das
List常用方法
public class ListMethod
public static void main(String[] args)
List list = new ArrayList();
list.add("张三丰");
list.add("秦天柱");
// add 插入一个对象
list.add(1,"lns");
System.out.println(list); // [张三丰, lns, 秦天柱]
List list2 = new ArrayList();
list2.add("风火轮");
list2.add("大黄蜂");
// addAll 插入所有元素
list.addAll(1,list2);
System.out.println(list); // [张三丰, 风火轮, 大黄蜂, lns, 秦天柱]
// indexOf 返回该对象首次出现的索引位置
System.out.println(list.indexOf("lns")); // 3
// lastIndexOf 返回该对象最后一次出现的索引位置
list.add(1,"张三丰");
System.out.println(list ); // [张三丰, 张三丰, 风火轮, 大黄蜂, lns, 秦天柱]
System.out.println(list.lastIndexOf("张三丰")); // 1
// set 替换对象数据
list.set(1,"妞妞");
System.out.println(list); // [张三丰, 妞妞, 风火轮, 大黄蜂, lns, 秦天柱]
// subList 返回范围为[fromIndex,toIndex)位置的子集合 该方法返回的是子串集合的地址索引
list = list.subList(0, 3);
System.out.println(list); // [张三丰, 妞妞, 风火轮]
ArrayList类
是由数组实现数据存储
特点:
-
元素可以是null,并且可以有多个
-
ArrayList是线程不安全的,不能在多线程的情况下使用
// 对比这两种源码 区别在于是否线程安全 synchronized // ArrayList源码 public boolean add(E e) modCount++; add(e, elementData, size); return true; // Vector源码 public synchronized boolean add(E e) modCount++; add(e, elementData, elementCount); return true;
ArrayList源码分析
-
ArrayList类数据存储在Object类数组中(elementData)
transient Object[] elementData; // transient 表示该属性不会被序列化
-
当使用无参构造方法创建该对象,初始elementData容量为0,第一次添加数据,扩容到10容量,以后每次扩容,则会扩大当前容量的1.5倍
-
如果使用指定大小的有参构造器,则初始elementData容量为指定大小,如果需要扩容,也是直接扩容1.5倍
扩容机制
无参构造器
1.设置断点
2.debug跳转
// 跳转1
public boolean add(E e)
modCount++; // 记录集合被修改的次数 如果madCount的值因为线程原因意外改变,则抛出异常
add(e, elementData, size); // e:传入的数据 elementDate:Object数组 size:数组元素数量
return true;
// 跳转2
private void add(E e, Object[] elementData, int s)
if (s == elementData.length) // s:数组元素数量 elementDate.length:数组容量
elementData = grow(); // 只有当容量够用,不会调用该方法
elementData[s] = e; // 数组添加数据
size = s + 1;
// 跳转3
private Object[] grow()
return grow(size + 1);
// 跳转4
private Object[] grow(int minCapacity) // minCapacity:当前元素个数+1
int oldCapacity = elementData.length; // 记录原容量
if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) //判断容量是否为0
// 传入newLength方法的参数:原容量,超出容量,0.5倍容量大小
int newCapacity = ArraysSupport.newLength(oldCapacity,
minCapacity - oldCapacity, oldCapacity >> 1 ); // >> 1 相当于乘0.5
return elementData = Arrays.copyOf(elementData, newCapacity); // 扩容,保留原数据
else
return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
// DEFAULT_CAPACITY 10 如果是容量为0,第一次扩容默认为10
// 当传入第11个数据时候跳转5
public static int newLength(int oldLength, int minGrowth, int prefGrowth)
// assert oldLength >= 0
// assert minGrowth > 0
int newLength = Math.max( minGrowth,prefGrowth ) + oldLength; // 当超出容量,则扩容1.5倍
if (newLength - MAX_ARRAY_LENGTH <= 0)
return newLength;
return hugeLength(oldLength, minGrowth);
有参构造器
public ArrayList(int initialCapacity)
if (initialCapacity > 0)
this.elementData = new Object[initialCapacity];
else if (initialCapacity == 0)
this.elementData = EMPTY_ELEMENTDATA;
else
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
Vector类
是由数组实现数据存储
Vector的基本介绍
// Vector的类定义
public class Vector<E>extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
// Vector底层本质也是对象数组
protected Object[] elementData;
// Vector是线程安全
// 通常方法被 synchronized 关键字修饰
Vector源码分析
/*
* The amount by which the capacity of the vector is automatically
* incremented when its size becomes greater than its capacity. If
* the capacity increment is less than or equal to zero, the capacity
* of the vector is doubled each time it needs to grow.
* 当向量的大小变得大于其容量时,向量的容量自动增加的量。如果容量增量小于或等于零,
* 则每次需要增长时,向量的容量都会增加一倍
* @serial
*/
protected int capacityIncrement;
private Object[] grow(int minCapacity)
int oldCapacity = elementData.length;
int newCapacity = ArraysSupport.newLength(oldCapacity,minCapacity - oldCapacity, capacityIncrement > 0 ? capacityIncrement : oldCapacity);
return elementData = Arrays.copyOf(elementData, newCapacity);
public static int newLength(int oldLength, int minGrowth, int prefGrowth)
// assert oldLength >= 0
// assert minGrowth > 0
int newLength = Math.max(minGrowth, prefGrowth) + oldLength; // 2倍
if (newLength - MAX_ARRAY_LENGTH <= 0)
return newLength;
return hugeLength(oldLength, minGrowth);
Vector和ArrayList的比较
底层结构 | 版本 | 线程安全 | 扩容机制 | |
---|---|---|---|---|
ArrayList | 可变数组 | jdk1.2 | 不安全,但效率高 | 如果有参构造 扩容1.5倍;如果是无参1.第一次默认10,第二次扩容1.5倍 |
Vector | 可变数组 | jdk1.0 | 安全,但效率不高 | 如果有参构造 扩容2倍;如果是无参1.第一次默认10,第二次扩容2倍 |
LinkedList类
LinkedList类基本介绍
- LinkedList类底层实现了双向链表和双端队列特点
- 可以添加任意元素包括null,并且可以重复
- 线程不安全没有实现同步
LinkedList类的底层结构
-
该类底层是一个双向链表
-
其中含有两个属性:first 和 last 分别指向首节点和尾节点
-
每个节点里面含有prev,next,item三个属性,其中通过prev指向前一个节点,通过next指向后一个节点,用item来存储数据
-
进行添加和删除操作,效率比数组高
添加数据源码分析
// 添加第一个数据
// 跳转1
public boolean add(E e) // 增加数据
linkLast(e);
return true;
// 跳转2
void linkLast(E e)
final Node<E> l = last; // last:null 第一次添加last为null
final Node<E> newNode = new Node<>(l, e, null); //l:null e:"lns" 说明prev和next指向null
last = newNode; // last 指向尾节点
if (l == null) // 添加第一个节点
first = newNode; // first和last都指向同一个节点
else
l.next = newNode;
size以上是关于常用集合类的主要内容,如果未能解决你的问题,请参考以下文章
Nvidia 擎天柱 NvOptimusEnablement
在 LG 擎天柱上使用 RingtoneManager.getRingtone