Collection
Collection是单列集合的祖宗接口,它的功能是全部单列集合都可以继承使用的
- List接口的实现类
- ArrayList:动态数组实现,允许重复元素
- LinkedList:双向链表实现,允许重复元素
- Set接口的实现类
- HashSet:基于哈希表实现,不允许重复元素
- LinkedHashSet:基于哈希表和链表实现,不允许重复元素,保持插入顺序
- TreeSet:基于红黑树实现,不允许重复元素,元素自动排序
collection方法
- 把给定的对象添加到当前集合中
1. 如果我们向List系列集合中添加数据,那么方法永远会返回true,因为List系列是允许元素重复
2.如果我们向Set系列集合中添加数据,那么方法会根据是否存在而返回true或false,因为Set系列是不允许元素重复的
Collection<E> coll = new ArrayList<> ();
coll.add(e);
- 清空集合中所有的元素
Collection<E> coll = new ArrayList<> ();
coll.add(e);
coll.clear();
- 把给定的对象在当前集合中删除
1.这个方法会返回一个布尔类型的值,当要删除的元素不存在,就会返回false
2. 因为Collection里面定义的是List和Set共性的方法,所以不能通过索引进行删除,只能通过元素的对象进行删除
Collection<E> coll = new ArrayList<> ();
coll.add(e);
coll.remove(e);
- 判断当前集合中是否包含给定的对象
在源码中contains方法是依赖equals方法进行判断是否存在,因此如果集合中存储的是自定义对象,在JavaBean中一定要重写equals方法
Collection<E> coll = new ArrayList<> ();
coll.add(e);
coll.contains(e);
- 判断当前集合是否为空
Collection<E> coll = new ArrayList<> ();
coll.isEmpty();
- 返回集合元素中个数/集合的长度
Collection<E> coll = new ArrayList<> ();
coll.size();
Collections
Collections是集合的工具类
- 打乱集合中的元素
Collection<E> coll = new ArrayList<> ();
Collections.shuffle(coll);
- 获取集合中的最大值
Collection<E> coll = new ArrayList<> ();
Collections.max(coll);
- 批量添加元素
Collection<E> coll = new ArrayList<> ();
Collections.addAll(coll,"1","2","3");
- 排序
Collection<E> coll = new ArrayList<> ();
//按照指定规则进行排序
Collections.sort(list, Comparator<T> c);
- 以二分查找查找元素
Collection<E> coll = new ArrayList<> ();
Collections.binarySearch(coll, T key);
- 拷贝集合中的元素
Collection<E> coll = new ArrayList<> ();
//将coll拷贝到target
Collections.copy(target, coll);
- 交换集合指定位置的元素
Collection<E> coll = new ArrayList<> ();
Collections.swap(coll, 1, 2);
遍历方法
迭代器遍历
1.迭代器在遍历集合的时候不依赖索引
2. 迭代器遍历完毕,指针不会复位,如果还要进行遍历,则需要重新获取一个迭代器对象
3. 一个循环中只能使用一次next方法,不然可能会报NoSuchElementException错误
4. 迭代器在遍历的时候,不能用集合的方法进行增加和删除,但是可以用迭代器提供的remove方法进行删除
Collection<String> collection = new ArrayList<>();
collection.add("aaa");
collection.add("bbb");
collection.add("ccc");
// 获取集合的迭代器对象,用于遍历集合中的所有元素
Iterator<String> iterator = collection.iterator();
//hasNext():判断当前位置是否有元素
while (iterator.hasNext()) {
//next():获取当前位置的元素,并将迭代器对象移向下一个位置
String element = iterator.next();
if ("bbb".equals(element)) {
//用迭代器提供的remove进行删除
iterator.remove();
}
System.out.println(element);
}
增强for遍历
增强for的底层就是迭代器,为了简化迭代器的代码而存在的
Collection<E> collection = new ArrayList<>();
for (E e : collection){
//这里的e相当于是定义了一个变量e,然后将collection的值赋给了e,所以当修改e的变量时,并不会修改原本的数据
System.out.println(e);
}
lambda表达式
lambda表达式允许以简洁的语法编写匿名内部类。Lambda表达式主要用于实现单个抽象方法的接口,这种接口被称为函数式接口(Functional Interface),这是一个只有一个抽象方法的接口。
Collection<E> collection = new Collection<> ();
//利用匿名内部类的形式
collection.forEach(new Consumer<E>(){
@Override
public void accept(E e) {
System.out.println(e);
}
});
//用lambda表达式简化
collection.forEach(e -> System.out.println(e));
List
List集合特有方法
- 在集合的指定位置插入指定的元素
ArrayList<E> list = new ArrayList<> ();
list.add(e1);
//在集合的指定位置插入指定的元素
list.add(1,e1);
- 删除指定索引处的元素,返回被删除的元素
ArrayList<E> list = new ArrayList<> ();
list.add(e);
//删除指定索引处的元素,返回被删除的元素
E res = list.remove(0);
ArrayList<Integer> list = new ArrayList<> ();
list.add(1);
list.add(2);
list.add(3);
list.add(1);
//此时删除的是索引1处的元素,而不是大小等于1的元素
//因为在调用方法的时候,如果方法出现了重载现象,会优先调用实参和形参类型一致的那个方法
//这里的1的是基本数据类型int,所以调用了删除索引处元素的remove方法
list.remove(1);
//如果要删除大小等于1的元素,可以参照如下
list.remove(Integer.valueOf(1));
- 修改指定索引处的元素,返回被修改的元素
ArrayList<E> list = new ArrayList<> ();
list.add(e);
//修改指定索引处的元素,返回被修改的元素
E res = list.set(0,i);
- 返回指定索引处的元素
ArrayList<E> list = new ArrayList<> ();
list.add(e);
//返回指定索引处的元素
E res = list.get(0);
遍历方法
- 迭代器遍历
- 增强for循环
- lambda表达式
- 普通for循环
- 列表迭代器(可以在遍历过程中添加,修改元素)
列表迭代器还可以反向遍历集合,用hasPrevious() 和 previous()
。
ArrayList<E> list = new ArrayList<> ();
ListIterator<E> it = list.listIterator();
while (it.hasNext()) {
E e = it.next();
if (i.equals(e)) {
//调用迭代器中的方法添加元素
it.add(i);
//调用迭代器中的方法修改元素
it.set(i);
}
}
ArrayList
ArrayList集合原理:
- 利用空参创建的集合,在底层创建一个默认长度为0的数组
- 添加第一个元素时,底层会创建一个新的长度为10的数组
- 当数组存满时,会扩容1.5倍
- 如果一次添加多个元素,1.5倍还放不下,则创建数组的长度和实际需要的长度一致
LinkedList
LinkedList的底层数据类型是双链表,因此有很多首尾操作的特有API
-
在列表开头插入特定的元素
public void addFirst(E e)
-
将指定的元素追加到列表的末尾
public void addLast(E e)
-
返回列表中的第一个元素
public E getFirst()
-
返回列表中的最后一个元素
pubic E getLast()
-
在列表中删除并返回第一个元素
public E removeFirst()
-
在列表中删除并返回最后一个元素
public E removeLast()
Set
HashSet
哈希值:
- 根据hashCode方法算出来的int类型的整数
- 所有对象都有哈希值,默认使用的地址值进行计算
- 一般来说,会重写hashCode方法,利用对象内部的属性值计算哈希值
- 在小部分情况下,不同属性值或者不同地址值计算出来的哈希值可能一样(哈希碰撞)
HashSet底层原理:
- 创建一个默认长度16,默认加载因为0.75的数组,数组名为table
- 根据元素的哈希值跟数组的长度计算出应存入的位置
- 判断当前位置是否为null,如果是null直接存入
- 如果位置不为null,表示有元素,则调用equals方法比较属性值
- 一样:不存;不一样:存入数组,形成链表,新元素直接挂在老元素下面(JDK8以前新老元素位置相反)
LinkedHashSet
LinkedHashSet底层原理:底层数据结构依然是哈希表,只是每个元素又额外多了一个双链表的机制记录存储的顺序,因此有序(存储和取出的元素顺序一致)
TreeSet
TreeSet的底层原理:这是基于红黑树的数据结构实现排序的,增删改查性能都较好
Treeset集合默认的排序规则:
- 对于数值类型:Integer,Double,默认按照从小到大的顺序进行排序
- 对于字符,字符串类型:按照字符在ASCII码表中的数字升序进行排序
两种更改排序的方法:
- 自然排序:Javabean类实现Comparable接口指定比较规则
public clss T implements Comparable<T> {
private String name;
private String id;
...
@Override
public int compareTo(T t) {
//this:表示当前要添加的元素
//t:表示已经在红黑树存在的元素
//返回值:
//负数:认为要添加的元素是小的,存左边
//正数:认为要添加的元素是大的,存右边
//0:认为要添加的元素已经存在,舍弃
return this.getId() - t.getId();
}
}
- 比较器排序:创建TreeSet对象时候,传递比较器Comparator指定规则
使用原则:默认使用第一种,如果第一种不能满足当前要求,才使用第二种
TreeSet<String> ts = new TreeSet<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
//定义比较规则
int i = o1.length() - o2.length();
i = i == 0 ? o1.compareTo(o2) : i;
//返回值规则和自然排序一样
return i;
}
//lambda表达式改写
TreeSet<String> ts = new TreeSet<>((o1,o2) -> {
//定义比较规则
int i = o1.length() - o2.length();
i = i == 0 ? o1.compareTo(o2) : i;
//返回值规则和自然排序一样
return i;
});
})
独有方法
由于TreeSet
是有序的,可以使用下列方法获得第一个和最后一个元素:
- 返回集合中的第一个元素(first)
TreeSet<Integer> ts = new TreeSet<> ();
int first = ts.first();
- 返回集合中的最后一个元素(last)
TreeSet<Integer> ts = new TreeSet<> ();
int first = ts.last();
使用场景
- 想要集合中元素可重复
ArrayList集合,基于数组的
- 想要集合中元素去重
HashSet集合,基于哈希表的
- 想要集合中元素可重复,而且当前增删操作明显多于查询
LinkedList集合,基于链表的
- 想要集合中元素去重,并且保证存取顺序
LinkedHashSet集合,基于哈希表和双链表,效率低于HashSet
- 想要集合中元素进行排序
TreeSet集合,基于红黑树,后续也可以用List集合实现排序
评论区
请登录后发表评论