技术问答-6 java中的集合(1)-数组集合比较、集合框架概述
1. 数组集合比较
- 数组和集合都是容器;
- 数组不是面向对象的,存在明显的缺陷,集合弥补了数组的缺陷,比数组更实用,而不同的集合框架类可适用不同的场合
说明:- 数组能存放基本数据类型和引用类型,而集合只能存放引用类型
- 数组长度固定无法改变,集合能动态改变
- 数组无法判断实际存储元素数量,length属性只告诉我们数组的容量,而集合的size方法表示的是集合元素的个数
- 数组是java语言内置数据类型,他是一个线性序列,所以他可以快速的访问其他元素,但是速度是要付出代价的,代价就是长度固定了,不能改变啦啦啦
- 集合以类的形式存在,具有封装、继承、多态等特性,通过简单的方式和属性既可以实现各种复杂的操作,大大提高了开发效率
2.集合框架概述
一、概述
Java Collection Framework(JCF) 提供给了我们一系列的类和接口,方便开发者处理集合对象。
在Java1.2之前,java没有完整的集合框架,而只有一些简单的可以自扩展的容器类,比如:Vector Stack HashTable 等。这些容器类在使用过程中由于效率问题饱受诟病,因此在java1.2中,java设计者们进行了大刀阔斧的整改,重新设计,于是就有了现在的集合框架。
新的集合框架木有弃用之前的容器类库,主要是为了向下兼容,但是我们在平台使用中尽少使用
Java集合框架大部分在java.util包中,此处还有一系列并发集合在java.util.concurrent包中,在java1.7之后添加了泛型机制,运行时类型转换问题提前到了编译时期~
二、整体框架
- 从图中可以看到Java集合框架主要分为2大类,一种是集合(Collection),另一种是图(Map),Collection可以理解为一个大小可变,提供各种操作数据方法的数组,而Map是一种ket-value数据结构的集合。java集合框架的通用实现类都提供2个标准的构造方法,一个是无参构造,一个是用来初始化集合大小的有构造参数,但这并不是java强制规范,但是集合框架中所有的通用类都遵循这个规则
- Collection是存储一组对象的集合的容器,他主要有以下三个子接口:
名称 | 说明 |
---|---|
List | 可以有重复元素的有序集合 |
Set | 没有重复元素的无序集合 |
Queue | jdk1.5后新增的队列数据结构,主要是为存储数据设计,而不是处理数据,适合做FIFO(先进先出策略) |
- Map并不是真正意义上的集合(are not true collection),但是这个接口提供了集合视角,使得可以像集合一样操作它们,具体如下:
- Map的所有key集合 Set keySet()
2)Map的所有value集合 Collection values
3)Map的内容看做ket-value映射的集合Set<Map<K,V>> entrySet()
三、Iterable接口
Iterable接口是Java集合框架的顶级接口,实现此接口使集合对象可以通过迭代遍历自身元素
序号 | 修饰符和返回值 | 方法名 | 描述 |
---|---|---|---|
1 | Iterator | iterator() | 返回一个内部元素为T的迭代器 |
2 | default void | forEach(Cosumer<? super T>) action | jdk1.8后加上的 ,对内部元素进行遍历,并对元素进行指定操作 |
3 | default Spliterator | spliterator() | jdk1.8后加上的 ,创建并返回一个可分割迭代器,多线程并行处理集合(需要考虑安全问题) |
顺便说一下:jdk1.8加了default关键字,被其修饰的方法可以不必由子类实现,并且default修饰的方法在接口中有方法体,这打破了java之前对接口方法的规范
List<String> list = new ArrayList<String>();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
// Iterator
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String str = it.next();
System.out.println(str);
}
List<String> list = new ArrayList<String>();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
// forEach
list.forEach(new Consumer<String>() {
@Override
public void accept(String t) {
System.out.println(t);
}
});
package along;
import java.util.Spliterator;
import java.util.function.Consumer;
public class MyThread4Spliterator<T> extends Thread{ // 寄存变量
private Spliterator<T> list;
// 构造 - 传递参数
public MyThread4Spliterator(Spliterator<T> list) {
setList(list);
}
// 线程调用run
@Override
public void run() {
Spliterator<T> list2 = getList();
list2.forEachRemaining(new Consumer<T>() {
@Override
public void accept(T t) {
System.out.println("线程 "+Thread.currentThread().getName() + " === "+ t);
}
});
}
public Spliterator<T> getList() {
return list;
}
public void setList(Spliterator<T> list) {
this.list = list;
}
}
package along;
import java.util.ArrayList;
import java.util.Spliterator;
public class javaTest {
public static void main(String[] args) {
// 初始化list
ArrayList<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < 200; i++) {
list.add(i + 1);
}
//四线程均分配比方式
Spliterator<Integer> spliterator01 = list.spliterator(); //01中有20个元素
Spliterator<Integer> spliterator02 = spliterator01.trySplit(); //01中有10个元素,02中有10个元素
Spliterator<Integer> spliterator03 = spliterator01.trySplit(); //01中有5个元素,02中有10个元素,03中有5个元素
Spliterator<Integer> spliterator04 = spliterator02.trySplit(); //01中有5个元素,02中有5个元素,03中有5个元素,04中有5个元素
MyThread4Spliterator<Integer> t01 = new MyThread4Spliterator<Integer>(spliterator01);
MyThread4Spliterator<Integer> t02 = new MyThread4Spliterator<Integer>(spliterator02);
MyThread4Spliterator<Integer> t03 = new MyThread4Spliterator<Integer>(spliterator03);
MyThread4Spliterator<Integer> t04 = new MyThread4Spliterator<Integer>(spliterator04);
t01.setName("001");
t02.setName("002");
t03.setName("003");
t04.setName("004");
t01.start();
t02.start();
t03.start();
t04.start();
}
}
注意:
trySplit 是分割集合
forEachRemaining是顺序遍历剩下的元素