Java 学习速记三:集合一
Collection体系继承树
简介
由于我们在编程的时候经常需要一个容器来承装我们都不确定数量的对象,有时候这些对象还有固定的映射需求,所以需要集合类的来解决这个需求。集合类主要干的活儿就是保存、盛装其它数据,因此集合类也称为容器类
集合类的特点:
1、集合只用于存储对象。
2、集合长度是可变的。
3、集合可以存储不同类型的对象。
集合与数组对比
1、数组初始化后,其长度就确定了;而集合是可以动态扩展容量的。
2、数组一旦定义好,就只能存储指定类型数据,集合存放类型可以不是一种。
3、数组时java语言内置数据类型,是线性排序的,查询执行效率或者类型检查都很快,但是对于添加、删除、插入操作效率不高。
实现类具体使用选择场景:
Collection 共性接口
添加 | add(Object o):添加 addAll(Collection c):把集合c里所有元素添加到指定合集里 |
---|---|
删除 | remove(Object o):删除 removeAll(Collection c):从集合中删除集合c里包含的所有元素 clear() |
判断 | contain(Object o):返回集合里是否包含指定元素 containsAll(Collection c):返回集合里是否包含集合c里的所有元素 isEmpty():返回集合是否为空 |
获取 | iterator():返回iterator对象用于遍历集合里的元素 size():返回集合里元素的个数 |
交集 | retainAll(Collection c):从集合中删除c里不包含的元素 |
转换成数组 | toString():把集合转换成数组 |
复制 | clone():浅拷贝 |
部分示例:
public class CollectionTest
{
public static void main(String[] args)
{
//创建实例
Collection c=new ArrayLsit();
//添加实例
c.add("测试字符1");
c.add(6);
//获取个数
System.out/print("c集合的元素个数为:"+c.size());
//删除
c.remove(6);
....
}
}
各种遍历方式:
public class CollectionEach {
public static void main(String[] args)
{
var books=new HashSet();
books.add("水浒传");
books.add("红楼梦");
books.add("西游记");
books.add("三国演义");
//for遍历
int booksSize = books.size();
Iterator<Integer> iterator = books.iterator();
for (int i = 0; i < booksSize ; i++) {
iterator.remove();//或者 list.remove(0);或者使用,list.remove(list.get(0));
}
//Lambda遍历
books.forEach(obj-> System.out.println("迭代集合元素:"+obj));
//froeach遍历
for (var obj:books){
var book=(String)obj;
System.out.println("foreach迭代集合元素:"+book);
}
//迭代器,集合专属的遍历工具
Iterator<String> it = books.iterator();//创建迭代器对象
while (it.hasNext()){//判断下一个位置是否有元素
System.out.println("Iterator迭代集合元素:"+it.next());
}
}
}
迭代集合元素:水浒传
迭代集合元素:红楼梦
迭代集合元素:三国演义
迭代集合元素:西游记
…
set
特点:
无序集合,元素不可重复
简介:
Set接口是Collection的子接口,set接口没有提供额外的方法。但是比Collection接口更加严格了
HashSet
特点:
1.HashSet底层的实现其实是一个HashMap支持,然后HashMap的底层物理实现是一个Hash表,顺序遵循Hash排序
2.很好的存取和查找性能
判断两个元素相等: 两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。因此,存储到HashSet的元素要重写hashCode和equals方法
示例:
HashSet<String> hs = new HashSet<String>();
// Adding elements using add() method
hs.add("green");
hs.add("red");
System.out.println("HashSet elements : " + hs);
LinkedHashSet
特点:
HashSet的基础上,链表和哈希表组合的一个数据存储结构。在结点中增加两个属性before和after维护了结点的前后添加顺序。输出LinkedHashSet集合的元素时候,元素的顺序总是与添加顺序一致。
示例:
LinkedHashSet<String> hset = new LinkedHashSet<>();
hset .add("张三");
hset .add("李四");
hset .add("王五");
for (String name : hset ) {
System.out.println(name);
}
TreeSet
特点:
里面维护了一个TreeMap,都是基于红黑树实现的,可以实现排序
如果希望TreeSet能正常运作,TreeSet只能添加同一种类型对象
额外方法:
Comparator comparator() | 如果TreeSet采用了定制排序,则该方法返回定制排序所是哦那个的Comparator;如果TreeSet采用自然排序则返回null |
---|---|
Object first() | 返回集合中的第一个元素 |
Objet last() | 返回集合中的最后一个元素 |
Object lower(OBject e) | 返回集合中位于指定元素之前的元素 |
Object higher(OBject e) | 返回集合中位于指定元素之后的元素 |
SortedSet subSet(Object fromElement,Object toElement) | 返回此set的子集合,从fromElement(包含)到fromElement(不包含) |
示例:
//创建Stduent类实现Comparable接口,并指定泛化类型为Student
class Student implements Comparable<Student>{
private int age;
private String name;
public Student() {
}
public Student(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "age:" + age +
", name:" + name;
}
/*
需要在此方法中编写比较规则
用这个参数(age)和集合中的每一个对象的(age)比较,结果有三种:>0 <0 =0
返回=0:表相同
返回<0:会在左子树上找
返回>0:会在右子树上找
比较规则是我们自己定的,这里比较的是对象的年龄
*/
@Override//实现compareTo方法编写比较规则才能排序
public int compareTo(Student o) {
return this.age-o.age;//按年龄升序
}
}
public class TreeSetTest {
public static void main(String[] args) {
TreeSet<Student> ts = new TreeSet();
ts.add(new Student(10,"张三"));
ts.add(new Student(8,"李四"));
ts.add(new Student(12,"王五"));
ts.add(new Student(9,"赵六"));
for(Student stu:ts){
System.out.println(stu);
}
/*
输出结果:(按年龄age排序)
age:8, name:李四
age:9, name:赵六
age:10, name:张三
age:12, name:王五
*/
}
}
EnumSet
特点:
1.EnumSet是专门为枚举类设计的集合类,所有元素都必须是指定枚举类型的枚举值,与枚举类型一起使用的专用 Set 实现。
2.EnumSet的集合元素也是有序的,EnumSet以枚举值在Enum类内的定义顺序来决定集合元素的排序
方法:
专属方法 | 用途 |
---|---|
EnumSet allOf(Class elementType) | 创建一个包含指定枚举类里所有枚举值的EnumSet集合 |
EnumSet complementOf(EnumSet e) | 创建一个其元素类型与指定EnumSet里元素类型相同的EnumSet集合,新EnumSet集合包含原EnumSet集合所不包含的、此类枚举类剩下的枚举值(即新EnumSet集合和原EnumSet集合的集合元素加起来是该枚举类的所有枚举值)。 |
EnumSet copyOf(Collection c) | 使用一个普通集合来创建EnumSet集合。 |
EnumSet copyOf(EnumSet e) | 创建一个指定EnumSet具有相同元素类型、相同集合元素的EnumSet集合 |
EnumSet noneOf(Class elementType) | 创建一个元素类型为指定枚举类型的空EnumSet。 |
EnumSet of(E first,E…rest) | 创建一个包含一个或多个枚举值的EnumSet集合,传入的多个枚举值必须属于同一个枚举类。 |
EnumSet range(E from,E to) | 创建一个包含从from枚举值到to枚举值范围内所有枚举值的EnumSet集合。 |
示例:
//创建一个枚举
enum Session{
SPRING, SUMMER,FAIL,WINTER
}
public class EnumSetTest {
public static void main(String[] args) {
//1.创建一个包含Session(枚举类)里所有枚举值的EnumSet集合
EnumSet e1 = EnumSet.allOf(Session.class);
System.out.println(e1);//[SPRING, SUMMER, FAIL, WINTER]
//2.创建一个空EnumSet
EnumSet e2 = EnumSet.noneOf(Session.class);
System.out.println(e2);//[]
//3. add()空EnumSet集合中添加枚举元素
e2.add(Session.SPRING);
e2.add(Session.SUMMER);
System.out.println(e2);//[SPRING, SUMMER]
//4. 以指定枚举值创建EnumSet集合
EnumSet e3 = EnumSet.of(Session.SPRING,Session.FAIL);
System.out.println(e3);//[SPRING, FAIL]
//5.创建一个包含从from枚举值到to枚举值范围内所有枚举值的EnumSet集合。
EnumSet e4 = EnumSet.range(Session.SPRING,Session.FAIL);
System.out.println(e4);//[SPRING, SUMMER, FAIL]
//6.创建一个其元素类型与指定EnumSet里元素类型相同的EnumSet集合,
// 新EnumSet集合包含原EnumSet集合所不包含的枚举值
EnumSet e5 = EnumSet.complementOf(e4);
System.out.println(e5);//[WINTER]
}
}
各set实现类的性能分析
HashSet:性能比TreeSet好,特别是最常用的添加,查询等。因为,TreeSet需要额外的红黑树算法维护次序。
但只有当一个需要保持排序的Set的时候才应该使用TreeSet
方法 | 插入删除速度 | 查询速度 | 是否排序 | 线程安全 |
---|---|---|---|---|
HashSet | Set速度标杆 | Set速度标杆 | x | x |
LinkedHashSet | 比Hash慢 | 比HashSet快 | x | x |
TreeSet | 比Hash慢 | 比HashSet慢 | y | x |
EnumSet | Set中速度最快的 | Set中速度最快的 | y | x |