目录
3、HashSet的子类------LinkedHashSet集合
一、Collection集合
1.1 集合概述
①集合到底是什么呢?
集合:集合是java中提供的一种容器,可以用来存储多个数据
②集合和数组既然都是容器,他们有啥区别?
- 数组的长度是固定的,集合的长度是可变的。
- 数组中存储的是统一类型的元素,可以存储基本数据类型值,也可以存储引用数据类型
集合存储的都是对象,而且对象的类型可以不一致,在开发中一般当对象多的时候,使用集合存储。
1.2 集合框架
集合按照其存储结构可以分为两大类,分别是单列集合 java.util.Collection 和双列集合java.util.Map
- Collection:单列集合类的根接口,用于存储一系列符合某种规则的元素,它有两个重要的子接口,分别是java.util.List 和java.util.Set。其中List特点是元素有序、元素可以重复 ;set特点是元素无序,而且不可重复。List接口主要实现类类有java.util.ArrayList和java.util.LinkedList 。Set接口主要实现类有java.util.HashSet和java.util.TreeSet.
1.2.1 Collection集合体系图:
注意:
1.在学习使用集合的时候,学习顶层接口/抽象类中共性方法,因为所有子类都可以使用
2.在学习使用集合的时候,使用底层,因为顶层不是接口就是抽象类,不可以创建对象使用,需要使用底层子类创建对象使用。
1.2.2 常用集合的底层及特点
集合名 | 底层实现原理 | 特点 |
ArrayList | 数组 | 查询块,增删慢 |
LinkedList | 链表 | 查询慢,增删快 |
Vector(了解) | 数组 | 和ArrayList相似,但是它是线程安全的 |
HashSet | 哈希表 + 红黑树 | 无索引,不可存储重复元素,存取无序 |
LinkedHashSet | 哈希表 + 链表 | 无索引,不可存储重复元素,保证存取顺序 |
TreeSet(了解) | 二叉树 | 一般就用于排序 |
1.3 Collection 常用功能
java.util.Collection接口
所有的单列集合的最顶层接口,里面定义了所有单列集合共性的方法,任意的单列集合都可以使用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(); 把集合中的元素,存储到数组中 返回该数组
【代码演示】
public static void main(String[] args) {
//首先创建集合对象(ArrayList举例) 使用多态形式
Collection<String> coll = new ArrayList<>();
/*
Public Boolean add(E e);把给定的对象添加到当前集合中
*/
boolean b1 = coll.add("张三");
System.out.println(b1);
System.out.println(coll);
/*
Public Boolean remove(E e); 把给定的元素在当前集合中删除
*/
/*boolean b2 = coll.remove("张三");
System.out.println("b2"+b2);
System.out.println(coll);*/
/*
Public Boolean contains(E e); 判断当前集合中是否包含此元素
*/
boolean b4 = coll.contains("张三");
System.out.println(b4);
boolean b5 = coll.contains("李四");
System.out.println(b5);
/*
Public Boolean isEmpty(); 判断当前集合是否为空
*/
System.out.println(coll.isEmpty());
/*
Public int size(); 返回集合中元素的个数
*/
System.out.println(coll.size());
/*
Public Object[] toArray(); 把集合中的元素,存储到数组中 返回该数组
*/
coll.add("李四");
Object[] arr = coll.toArray();
for(int i=0;i<arr.length;i++){
System.out.println(arr[i]);
}
/*
Public void clear(); 清空当前集合中所有元素
*/
coll.clear();
System.out.println(coll);
}
二、List接口
1、 List接口介绍
Java.util.List 接口继承自 Collection 接口,是单列集合的一个重要分支,习惯性的会将实现类List接口的对象称为List集合。在List集合中允许出现重复的元素,所有的元素是以一种线性方式进行存储的,在程序中可以通过索引来访问集合中的指定元素,另外,List集合还有一个特点是集合元素有序,即元素的存入顺序和取出顺序一致。
1.1 List接口特点:
1)它是一个元素存取有序的集合,例如,村元素的顺序是11,22,33 那么集合中,元素的存储就是按照11,22,33的顺序完成的
2)它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是一个道理)
3)集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素。
1.2 List接口中带索引的方法(特有):
public void add(int index,E element);将指定的元素,添加到集合中指定的位置上
public E get(int index); 返回集合中指定的元素
public E remove(int index); 移除集合中指定位置的元素,并返回该元素
public E removeRange(int start,int end)该方法主要删除了在范围内的数据
public E set(int index,E element); 用指定元素替换集合中指定位置的元素,返回值为更新前的元素
注意:
1.操作索引的时候,一定要繁殖索引越界异常
2.IndexOutBoundsException 索引越界异常 集合会报
3.ArrayIndexOutBoundsException 数组索引越界异常
4.StringIndexOutBoundsException 字符串索引越界异常
2、 List的子类---ArrayList集合
java.util.ArrayList 是大小可变的数组的实现,存储在内的数据称为元素。此类提供一些方法来操作内部存储的元素。 ArrayList 中可不断添加元素,其大小也自动增加。
2.1、ArrayList类中常用方法
public boolean add(E e):将指定的元素添加到此集合的尾部。
public E remove(int index):移除此集合中指定位置上的元素。返回被删除的元素。
public E get(int index):返回此集合中指定位置上的元素。返回获取的元素。
public int size():返回此集合中的元素数。遍历集合时,可以控制索引范围,防止越界。
【代码演示】
public class ArrayListTest01 {
public static void main(String[] args) {
//创建集合对象
ArrayList<String> list = new ArrayList<String>();
//添加元素list.add("hello");
list.add("world");
list.add("java");
list.add("你好");
//public E get(int index):返回指定索引处的元素
System.out.println("get:"+list.get(0));
System.out.println("get:"+list.get(1));
System.out.println("get:"+list.get(2));
//public int size():返回集合中的元素的个数
System.out.println("size:" + list.size());
//public E remove(int index):删除指定索引处的元素,返回被删除的元素
System.out.println("remove:" + list.remove(0));
//遍历输出
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
}
注意事项:ArrayList对象不能存储基本类型,只能存储引用类型的数据。所以不能写ArrayList<int>等,但是存储基本数据类型对应的包装类型是可以的(自动装箱)。所以,想要存储基本类型数据,ArrayList<>中的数据类型,必须转换后才能编写,转换写法如下:
基本类型 | 基本类型包装类 |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
3、 List的子类---LinkedList集合
`java.util.LinkedList`集合数据存储的结构是链表结构。方便元素添加、删除的集合。它是一个双向链表。
3.1、LinkedList类中常用方法
实际开发中对一个集合元素的添加与删除经常涉及到首尾操作,而LinkedList提供了大量首尾操作的方法,如下所示:
public void addFirst(E e); 将指定元素插入到此列表的开头
public void addLast(E e); 将指定元素插入到此列表的结尾
public E getFirst(); 返回此列表的第一个元素
public E getLast(); 返回此列表的最后一个元素
public E removeFirst();移除此列表的第一个元素并返回该元素
public E removeLast();移除此列表的最后一个元素并返回该元素
public E pop();从此列表所表示的堆栈处弹出一个元素
public void push(); 将元素推入此列表所表示的堆栈
public Boolean isEmpty(); 判断是否包含元素
【代码演示】
public static void main(String[] args) {
//创建对象
LinkedList<String> link = new LinkedList<>();
//添加元素
link.addFirst("abc1");
link.addFirst("abc2");
link.addFirst("abc3");
System.out.println(link);
//获取元素
System.out.println(link.getFirst());
System.out.println(link.getLast());
//删除元素
System.out.println(link.removeFirst());
System.out.println(link.removeLast());
while (link.isEmpty()){ //判断集合是否为空
System.out.println(link.pop()); //弹出集合的栈顶的元素
}
System.out.println(link.isEmpty());
}
三、Set接口
1、Set接口
Java.util.Set 接口和Java.util.List接口一样,同样继承自Collection接口,它与Collection接口中的方法基本一致,并没有对Collection接口进行功能上的扩充,只是比collection接口更加严格了。与List接口不同的是 Set接口中元素无序,并且都会以某种规则保证存入的元素不出现重复。
1.1 Set接口的特点
1.不允许存储重复元素
2.没有索引,没有带索引的方法,也不能使用普通的for循环遍历,可以采用迭代器或者增强for
2、HashSet集合介绍
Java.util.HashSet是Set接口的一个实现类,它所存储的元素是不可重复的,并且元素都是无序的(即存取顺序不一致)。Java.util.HashSet底层实现其实是一个java.util.HashMap支持。
2.1 HashSet的特点
1.不循序存储重复的元素
2.没有索引,没有带索引的方法,也不能使用普通for循环遍历
3.是一个无序的集合,存储元素和取出元素的顺序有可能不一致
4.底层是一个哈希表结构(查询的速度非常快)
注意:
HashSet是根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存取和查找功能,保证元素唯一性的方式依赖于hashCode与equals方法。
2.2、hashCode
1.哈希值:是一个十进制的整数,由系统随机给出(就是对象的地址值,是一个逻辑地址,是虚拟出来得到的地址,不是根据数据实际存储的物理地址)
2.在Object类有一个方法,可以获取对象的哈希值,int hashCode() 返回该对象的哈希码值
3.hashCode方法 public native int hashCode() native代表该方法调用的是本地操作系统的方法
【代码演示】
定义一个Person类:
public class Persion {
}
测试类:
public static void main(String[] args) {
//Peresion类继承Object类所以可以使用Object类的hashCode方法
Persion p1 = new Persion();
int h1 = p1.hashCode();
System.out.println(h1);
Persion p2 = new Persion();
int h2 = p2.hashCode();
System.out.println(h2);
/*
toString方法的源码
return getClass().getName()+"@" +Integer.toString(hashCode());
*/
System.out.println(p1);
System.out.println(p2);
System.out.println(p1 == p2);
//注意一个特殊的字符串哈希值
String s1 = new String("abc");
String s2 = new String("abc");
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
System.out.println("重地".hashCode());
System.out.println("童话".hashCode());
}
2.3 HashSet存储自定义类型元素
给HashSet中存放自定义元素时,需要重写对象中的hashCode和equals方法 建立自己的比较方式,才能保证HashSet集合中的对象唯一。
【代码演示】
//创建Student类:
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
name.equals(student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
测试类:
public static void main(String[] args) {
//创建集合对象 该集合中存储Student类型对象
HashSet<Student> stuSet = new HashSet<>();
//存储
Student stu = new Student("于谦", 43);
Student stu1 = new Student("于谦", 43);
stuSet.add(stu);
stuSet.add(new Student("郭德纲",40));
stuSet.add(new Student("于谦",43));
stuSet.add(new Student("郭麒麟",23));
stuSet.add(stu);
//遍历
for(Student stu2:stuSet){
System.out.println(stu2);
}
}
3、HashSet的子类------LinkedHashSet集合
在HashSet下面有一个子类 java.util.LinkedHashSet,它是链表和哈希表组合的一个数据存储结构。
3.1、LinkedHashSet集合特点
底层是一个哈希表(数组+链表/红黑树)+链表,多了一条链表(记录元素的存储顺序),保证元素有序。
【代码演示】
public class LinkedHashSetDemo {
public static void main(String[] args) {
Set<String> set = new LinkedHashSet<>();
set.add("bbb");
set.add("aaa");
Iterator<String> it = set.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}