JavaSE Day16 集合 list set
JavaSE Day16 集合 list set
目录
比较器总结
基本数据类型,自然升序
应用数据类型,自然升序排序
字符串: 查看源码,字典排序,
不等,对应位的字符不等 或者 长度不等
自定义类
用重写的方法compareTo排序;
返回的是负数时,需要调换位置;
集合
容器,位于util包中
集合的继承关系,实现类等
集合和数组的区别
- 数组存储 基本类型和引用;
集合 只能存储 引用。 - 数组 长度是固定的;
集合 长度是不固定的。数据结构(数据的组织形式);消耗大
Collection 接口
特点:数据可以重复,无序
List接口
特点:数据可以重复,有序,线性排列;
实现类
- ArrayList: 数据结构是 数组
- Verctor: 数据结构也是数组,不建议使用;
- LinkedList:数据结构;链表
实现类比较
ArrayList:(出现晚一点)
- 底层是数组,默认初始容量为10,
- 扩容为:0.5倍扩容,重新创建一个数组,拷贝原始数组到新数组中;
- System.arraycopy 效率较高
- 性能较高,与verctor比
- 线程非安全,速度快,
- 可以使用其他类 包装;提高安全性;
Verctor:不常用,和ArrayList基本上一样,
- 底层是数组
- 遍历快,
- 插入和删除慢;
- 性能较低,与ArrayList比,
- 线程安全,但是慢
- 一般不用了;性能太低;
- 扩容1倍
LinkedList
- 底层是链表
- 单向链表
- Node节点,包含 数据域(值域)和链域(存在下一格元素地址的;)
- 最后一个元素的存储的地址为null
- 双向链表
- 前驱 数据域 后继,两个链域
- 前驱存储前一个元素的地址,后继存储后一个元素的存储地址;
- 遍历慢,或随机查找某个元素
- 插入和删除元素 快;
Collection API
package day16;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
public class TestCollection {
public static void main(String[] args) {
// Collection
// 创建一个集合
Collection<String> c = new ArrayList<>();
ArrayList<String> c3 = new ArrayList<>();
// 判断集合是否为空,集合元素的个数
System.out.println(c.isEmpty());//true
// 添加
c.add("aa");
c.add("bb");
c.add("cc");
c.add("ddd");
// 打印集合
System.out.println(c);
// 查看源码
System.out.println(c3.toString());
System.out.println(c.isEmpty());// false
// 添加的集合中的元素的个数;
System.out.println(c.size());
//
Collection<String> c1 = new ArrayList<>();
c1.add("ee");
c1.add("ff");
// 把参数集合中的所有元素,添加到当前集合中,当前集合只要发生了改变,就是true
c.addAll(c1);
System.out.println(c);
// 删除 参数指定的元素,只要当前集合发生了改变,返回true;
c.remove("bb");
System.out.println(c);
// 删除指定参数集合中的所有元素;
c.removeAll(c1);
System.out.println(c);
// 按照指定条件删除
/*c.removeIf(new Predicate<String>() {
@Override
public boolean test(String s) {
return s.length() == 3;
}
});
*/
c.removeIf(s -> s.length() == 3);
System.out.println(c);
// 参数指定的元素在集合中是否包含,包含就是true
System.out.println( c.contains("cc"));
// 参数集合中的所有元素 在当前集合是否包含,包含就是true
System.out.println(c.containsAll(c1));
// 把一个字符串数组 转换成集合
// 转换的集合 是Arrays的静态内部类ArrayList,
// 是一个固定长度的集合,不能像集合中添加或删除元素
List<String> c2 = Arrays.asList(new String[]{"ee","ff"});
//
c.addAll(c2);
System.out.println(c);
System.out.println(c.containsAll(c1));
// 集合转数组
Object[] obj = c.toArray(new Object[10]);// 默认为0,如果多了,多的元素就是null;
System.out.println(Arrays.toString(obj));
String[] str = c.toArray(new String[14]);
System.out.println(Arrays.toString(str));
// 清空元素
c.clear();
System.out.println(c.isEmpty());
System.out.println(c.size());
}
}
ArrayList API
package day16;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class TestList02 {
public static void main(String[] args) {
// List有顺序,按元素的添加的顺序,
List<String> list = new ArrayList<>();
list.add("aa");//索引0
list.add("bb");//1
list.add("cc");//2
list.add("dd");
System.out.println(list);
// 可以向索引位置添加元素
list.add(1,"xx");
System.out.println(list);
// 获得索引出的元素
System.out.println(list.get(1));
// 用第二参数元素,替换索引出的元素
list.set(1,"yy");
System.out.println(list);
//
list.add("aa");
System.out.println(list);
// 返回参数元素 在当前集合中 第一次出现的位置索引
System.out.println(list.indexOf("aa"));
// 返回参数元素 在当前集合中 最后一次出现的位置索引
System.out.println(list.lastIndexOf("aa"));
// 取子集,[起始位置,终止) 取到终止的前一位;
System.out.println(list.subList(1,4));
// 排序
System.out.println(list);
// 参数是 Comparator类型的比较器;
// 参数是 null,会按照Comparable的方式自然升序排序;
list.sort(null);
System.out.println(list);
list.sort(String::compareTo);
// list.sort((s1,s2)->s2.compare(s1))
// ;
System.out.println(list);
}
}
Iterator API
package day16;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.function.Consumer;
public class TestIterator {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("aa");
list.add("bb");
list.add("cc");
System.out.println(list);
// 遍历
// 1. 普通for
System.out.println("普通for");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
System.out.println("------------------------");
// 2. 增强for
System.out.println("增强for");
for (String s : list
) {
System.out.println(s);
}
System.out.println("-------------------------");
// 3. foreach
System.out.println("foreach");
/*
list.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);// s表示集合的元素
}
});
list.forEach(s -> System.out.println(s));
*/
list.forEach(System.out::println);
System.out.println("-------------------------");
// 4. Stream foreach
System.out.println("stream foreach");
list.stream().forEach(System.out::println);
System.out.println("-------------------------");
// 5. Iterator 迭代器
// 获得了一个迭代器
System.out.println("Iterator 迭代器");
Iterator<String> i = list.iterator();
/*System.out.println(i.next());
System.out.println(i.next());
// 删除的最近一次next(),所访问的元素
i.remove();
System.out.println(i.next());
System.out.println(list);*/
while (i.hasNext()) {
System.out.println(i.next());
//list.add("abc");
// 不能添加,会报错 穿行报错 java.util.ConcurrentModificationException
}
//System.out.println(i.next());
// 超过列表长度 报错 java.util.NoSuchElementException
System.out.println("-------------------------");
// 6. ListIterator
ListIterator<String> li = list.listIterator();
while (li.hasNext()) {
System.out.println(li.next());// 为什么不带有hello
li.add("hello");
}
// 向前遍历
while (li.hasPrevious()) {
System.out.println(li.previous());
}
System.out.println("-------------------------");
// 7. Iterator foreachremining 迭代器的迭代方法
Iterator<String> i1 = list.iterator();
i1.forEachRemaining(System.out::println);
System.out.println("-------------------------");
System.out.println("-------------------------");
}
}
Set 接口
特点:存储的数据唯一,无序
- 直接实现类,hashSet,linkedHashSet,
- sortedSet接口:排序
- NavigableSet接口:精确运算
- NavigableSet和sortedSet的实现类: TreeSet
HashSet:
-
底层结构是Hash
-
特点
- 哈希表
- 唯一,hashcode,equals,效率高
- 无序
Set<String> set = new HashSet<>(); set.add("aa"); set.add("bb"); set.add("cc"); System.out.println(set); boolean bool = set.add("aa"); System.out.println(set); System.out.println(bool);// false 表示添加失败
-
哈希算法:
-
哈希表:将一组关键字映射到地址集上;
-
注意:
首先hashCode()算出位置,存储元素,如果哈希冲突(算出的位置值,与之前存储过的元素的哈希值一样的,)调用equals判断是否为同一个对象,是同一个,不存储采用旧的值,不同一个可以存储连式存储,节点个数超过8个采用 二叉树存储。 -
重写
- hashCode equals用自己的规则去重;
- 桶:数组+链表
TreeSet
- 底层数据结构是二叉树;
- 树:是由节点集及连接每对的有向边组成。 二叉树:形结构任意节点不能超过两个孩子。
- 根节点,枝节点:中间的节点; 叶节点:没有子节点的节点;
- 中序,左中右的遍历方式,
- 自然升序
- 自己制定顺序,Comparator,
- 必须有排序规则,否则报错,
- 当comparable或 comparator 比较为0时,TreeSet认为是一个元素,因此只保存一份;
linkedHashSet
- 链表和哈希表
- 按照元素的添加的顺序来维护的;
- 唯一
TreeSet API
SortedSet<String> set = new TreeSet<>();
set.add("cc");
set.add("bb");
set.add("aa");
System.out.println(set);
// 返回排过序的第一个元素,和最后一个元素
System.out.println(set.first());
System.out.println(set.last());
// [起始元素,终止元素) 取子集
set.subSet("aa","cc").forEach(System.out::println);
额外的知识点 - TreeSet去重(需要重新整理)
TreeSet在存储对象时,一般为了去重都会重写CompareTo方法,但是如果是比较的有2个属性,例如:先按名字排序,如果名字不同就按年龄排序,此时就会出现个别元素无法去重的情况。