1.Collection集合概述
- Java数组的长度是固定的,为了使程序能够方便地存储和操作数目不固定的一组数据,JDK类库提供了Java集合
- 与数组不同的是,集合中不能存放基本类型数据,而只能存放对象的引用。
- 数组只能存储同种数据类型的元素 ,集合可以存储不同类型的元素
1.1.List接口
- 有序集合(存取元素顺序相同)
- 允许存储相同的元素,多个null
- 有索引,可用 get(index),for遍历
实现List接口的集合
- Vector
- ArrayList(不扩容且尾加时性能可能超过LinkedList,因为后者要创建Node对象)
- LinkedList(遍历时尽量迭代器,get要每次从头遍历)
添加的方法
-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 | Vector | LinkedList | |
|---|---|---|---|
| 线程安全 | 否 | 是 | 否 |
| 底层实现 | 数组 | 数组 | 链表 |
| 性能 | 查询快,增删慢 | 最慢 | 增删快,查询慢 |
1.2.set接口
- 不允许存储重复元素,一个null
- 没有索引,只能迭代器遍历,不能用for遍历
实现set接口的集合
- TreeSet(无序集合)
- HashSet(无序集合)
- LinkedHashSet(有序集合)
| HashSet | TreeSet | LinkedHashSet | |
|---|---|---|---|
| 底层实现 | 哈希表(链表加数组) | 红黑树 | 哈希表和链表 |
| 元素是否能为null | 是 | 否 | 否 |
| 线程安全 | 否 | 否 | 否 |
1.3.Collection接口的共性方法
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() 把集合中的元素,存储到数组中。
1.4.迭代器
Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法,可用于迭代 ArrayList 和 HashSet 等集合。
public interface Iterator<E> {
boolean hasNext();
//hasNext() 用于检测集合中是否还有元素。
E next();
//会返回迭代器的下一个元素,并且更新迭代器的状态。
default void remove() {
throw new UnsupportedOperationException("remove");
}
//remove() 将迭代器返回的元素删除。
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
迭代输出ArrayList的元素
ArrayList q=new ArrayList();
q.add(1);
q.add(2);
q.add(3);
Iterator w=q.iterator();
while(w.hasNext())
{
System.out.println(w.next());
}
1.5.源码
package java.util;
import java.util.function.Predicate;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
/**
*这是一个集合分层的根接口。集合代表了一组包含元素的对象。有些集合允许有重复的元素,有些
不允许。
*有些集合是有序的有些无序的。jdk不对这个接口提供任何直接的实现,但是再一些直接子接口例如
Set和List有实现了某些接口方法。
*所有继承Collection的类必须提供两个默认的构造函数,一个不带参数的、一个带Collection类
型参数。
*/
public interface Collection<E> extends Iterable<E> {
// 查询操作
/**
*返回集合大小,也就是集合中元素的数量
*/
int size();
/**
* 如果集合包含元素返回true,即判断集合是否为空
*/
boolean isEmpty();
/**
* 判断集合是否存在某个对象,注意这里参数是个Object,并没有限制为E或其子类
*/
boolean contains(Object o);
/**
* 返回一个迭代器iterator。并没有说明元素的迭代顺序,除非特别的集合有这个要求。
*/
Iterator<E> iterator();
/**
*将集合转为对象数组,注意这里不是元素数组而是一个Object数组。
*如果集合保证是有序的,那么通过迭代器返回数组有相同顺序
*返回的数组是安全的,也就是说集合有自己的引用,数组开辟新的堆内存,也有自己的引用。所以调
*用者可以随意操作返回的数组。
*这个方法是数组和列表之间的桥梁
*/
Object[] toArray();
/**
* 返回一个集合元素类型的数组。如果集合满足指定的数组并且有足够的空间,则在其中返回此集合
* 否则返回此集合大小的新数组。
* 如果集合有序,那么返回此集合迭代器遍历顺序的数组
* 如果数组大小比集合元素多,那么在数组满足集合元素后在末尾设置为null
* 如果在这个集合中指定数组运行时类型不是运行时元素类型的超类,那么抛ArrayStoreException异常
* 如果指定数组为空,则抛出NullPointerException
*/
<T> T[] toArray(T[] a);
// 修改操作
/**
* 确保此集合包含特定的元素类型。
* 如果此集合增加元素成功返回true。
* 如果此集合不允许有重复元素并且已经包含所传参数,那么返回false
*
* 支持此操作的集合可能会限制向该集合添加哪些元素。特别的,有些集合会拒绝null元素,有些
* 会对要增加的元素强加一些限制。
* Collection实现类应该在文档中明确指出所有的限制。
* 如果集合以除已经包含元素之外的任何原因拒绝添加特定元素,则必须抛出异常
*(而不是返回false)。这保留了集合在此调用返回后始终包含指定元素的不变式。
*/
boolean add(E e);
/**
* 如果此集合中存在此元素,那么移除一个特定元素类型的实例。更正式的说,如果集合中包含一个或多个这样的元素,
* 那么删除这样的元素(o==null?e==null:o.equals(e))。如果集合包含指定的元素(或集合因调用而发生改变),那么返回true。
*
* 如果指定元素的类型和集合不相容,抛出ClassCastException异常(可选的限制条件)
* 如果指定元素是null并且这个集合不允许null元素存在,那么抛出NullPointerException异常(可选的限制条件)
* 如果此集合不支持remove操作那么抛出UnsupportedOperationException异常(可选的限制条件)
*/
boolean remove(Object o);
// 容量操作
/**
* 如果this集合包含指定集合的所有元素,返回true
* c集合必须要检查是否被包含在this集合
* 如果指定元素的类型和集合不相容,抛出ClassCastException异常(可选的限制条件)
* 如果指定元素是null并且这个集合不允许null元素存在,那么抛出NullPointerException异常(可选的限制条件)
*/
boolean containsAll(Collection<?> c);
/**
* 将指定集合的所有元素到this集合中(可选的操作)。
* 如果指定的集合在操作进行时被修改了,那么此操作行为未定义。
* (这意味着如果指定的集合是这个集合,并且这个集合是非空的,那么这个调用的行为是未定义的。)
*
* @参数:c集合包含了要被添加到这个集合的元素
* @返回:如果调用结果改变了this集合返回true
* @throws:如果 addAll操作不被此集合支持,那么抛出UnsupportedOpertaionException异常
* @throws: 如果指定集合包含了空元素而this集合不允许有空元素,那么抛出NullPointerException异常
* @throws:如果this集合阻止hiding集合元素类型添加,那么抛出ClassCastException异常
* @throws:如果指定集合的元素的某些属性阻止将其添加到此集合,则抛出IllegalArgumentException
* @throws:由于插入限制,如果不是所有元素都可以在此时添加,则抛出IllegalStateException异常
*/
boolean addAll(Collection<? extends E> c);
/**
* 移除此集合中所有的包含在指定集合中的元素(可选的操作)。调用过此函数之后,那么此集合和指定集合将不再包含相同元素。
* @param:包含要从该集合中删除的元素的c集合
* @return:如果此集合因调用而更改那么返回true
* @throws:如果此集合不支持removeAll方法,则抛出UnsupportedOperationException
* @throws:如果集合中一个或多个元素的类型与指定集合不兼容,则抛出ClassCastException(可选的操作)
* @throws:如果该集合包含一个或多个空元素,且指定的集合不支持空元素(optional),或者指定的集合为空,
* 则抛出NullPointerException异常
*/
boolean removeAll(Collection<?> c);
/**
* 移除此集合中所有符合给定Predicate的元素。在迭代期间或由Predicate引发的错误或运行时异常将被转发给调用方
* @implSpec
* 默认实现使用其迭代器遍历集合的所有元素。每一个匹配的元素使用iterator.remove()来移除。
* 如果集合的iterator不支持移除将会抛出UnsupportedOperationException异常在匹匹厄到
* 第一个元素时。
* @param 过滤一个predicate
* @param 筛选要删除的元素返回true的Predicate
* @return 如果任何一个元素被删除返回true
* @throws 指定过滤器为空,抛出NullPointerException
* @throws 如果元素没有被删除,或者移除操作不支持,
* 则立即抛出UnsupportedOperationException异常
* @since 1.8
*/
default boolean removeIf(Predicate<? super E> filter) {
//如果filter为null抛出NullPointerException
Objects.requireNonNull(filter);
boolean removed = false;
final Iterator<E> each = iterator();
//通过迭代器遍历删除,只要删除一个removed就为true
while (each.hasNext()) {
if (filter.test(each.next())) {
each.remove();
removed = true;
}
}
return removed;
}
/**
* 只保留此集合中包含在指定集合中的元素(可选的操作)。
* 也就是说,此集合中不包含在指定集合中的所有元素。
* @param:要保留的元素的集合c
* @return:如果此集合改变了返回true
* @throws:如果此集合不支持retainAll,则抛出UnsupportedOperationException异常
* @throws:如果集合中一个或多个元素的类型与指定集合不兼容,则抛出ClassCastException(可选的操作)
* @throws:如果该集合包含一个或多个空元素,且指定的集合不支持空元素(optional),或者指定的集合为空
*/
boolean retainAll(Collection<?> c);
/**
* 移除此集合中所有元素(可选操作),调用此方法后集合里将为空。
* @throws: 如果此集合clear操作不支持将会抛出UnsupportOperationException异常。
*/
void clear();
// 比较和hash
/**
* 比较指定的对象与此集合是否相等
*
*/
boolean equals(Object o);
/**
*返回这个集合的hashCode。当集合接口没有对Object.hashCode方法的一般协议做任何规定,编程
*人员应该注意在重写equals方法时必须重写hashCode方法,以便满足一般协议对这个
*Object.hashCode方法。特别的,c1.equals(c2)表明c1.hashCode()==c2.hashCode()。
*/
int hashCode();
/**
*一下1.8新增的Spliterator,暂不研究
*/
@Override
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, 0);
}
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
}
2.Map
1、接口 Map<K,V>
- 将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。
Map<key,value> 对象名=new 子类<key,value>();
- 特点:键不可以重复
2、Map实现类--HashMap集合
- 基于哈希表的
Map接口的实现。此实现提供所有可选的映射操作,并允许使用null值和null键。(除了非同步和允许使用 null 之外,HashMap类与Hashtable大致相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
- 特点:线程不安全集合、顺序不一定
HashMap遍历方式
3、Map实现类--LinkedHashMap集合
Map接口的哈希表和链接列表实现,具有可预知的迭代顺序。此实现与HashMap的不同之处在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序通常就是将键插入到映射中的顺序(插入顺序)。注意,如果在映射中重新插入 键,则插入顺序不受影响。
- 特点:线程不安全、具有迭代顺序
4、Hashtable集合
- 此类实现一个哈希表,该哈希表将键映射到相应的值。任何非
null对象都可以用作键或值。
- Hashtable线程安全,运算速度慢。HashMap线程不安全,运算速度快
- 从JDK1.2开始Hashtab就被HashMap代替
- HashMap允许存储null值null键,而Hashtable不允许
- Hashtable的子类Provider哈活跃在开发中