目录
1.Collection集合接口
2.List 接口 (常用子类 ArrayList ,LinkedList,Vector)
3.Set 集合 接口(常用子类 HashSet LinkedHashSet,TreeSet)
4.集合输出(iterator , Enumeration)
1.Collection集合接口
Collection是集合中最大父接口,在接口中定义了核心的一些操作。
Collection接口定义的核心方法:
方法名 | 描述 | 方法修饰符 | 参数 | 返回值类型 |
---|---|---|---|---|
add(E element) | 将指定元素添加到集合中 | public | element: 要添加的元素 | boolean |
remove(Object o) | 从集合中移除指定元素 | public | o: 要移除的元素 | boolean |
get(int index) | 获取集合中指定位置的元素 | public | index: 元素的索引 | E |
clear() | 清空集合中的所有元素 | public | 无 | 无 |
size() | 返回集合中的元素数量 | public | 无 | int |
toArray() | 将集合转换为数组 | public | 无 | Object[] |
iterator() | 返回集合的迭代器 | public | 无 | Iterator<E> |
contains(Object o) | 检查集合是否包含指定元素 | public | o: 要检查的元素 | boolean |
2.List 接口 (常用子类 ArrayList ,LinkedList,Vector)
List实现了Collection接口,但是自己也扩充了一些方法:
List扩充的方法:
方法名 | 描述 |
---|---|
get(int index) | 获取列表中指定位置的元素 |
set(int index, E element) | 用指定元素替换列表中指定位置的元素 |
ListIterator() | 返回列表的列表迭代器 |
foreach(Consumer<? super E> action) | 对列表中的每个元素执行指定操作 |
1.ArrayList 线性表
作为一个线性标其存储方式是数组模式,以下是一个ArrayList的案例代码
实现ArrayList存放字符串类型的火车
package Example1801;
import java.util.ArrayList;
import java.util.List;
public class javaDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("火车头");
list.add("车厢1");
list.add("车厢2");
list.add("车厢3");
// 获取基础信息
System.out.println("集合是否为空?"+list.isEmpty()+" 集合内容的个数"+list.size());
// 调用方法判断是否存在字符串
System.out.println(list.contains("火车头"));
// 获取下标为0的内容
System.out.println("下标为0的内容是"+list.get(0));
// 移除数据
list.remove("车厢3");
// 非标准输出,了解即可,标准输出接口是Iterator
list.forEach(str->{
System.out.println(str);
});
// 清空集合内的数据
list.clear();
System.out.println(list.isEmpty());
}
}
2.LinkedList 链表
作为链表,其实现的方法与火车类似,定义一个空间(车厢)再接在火车最后一列车厢上。由于LinkedList都是遵循了
案例代码:
package Example1804;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class javaDemo {
public static void main(String[] args) {
// 创建链表并插入数据
List<String> linkedList = new LinkedList<String>();
linkedList.add("火车头");
linkedList.add("火车车厢1");
linkedList.add("火车车厢2");
linkedList.add("火车车厢3");
linkedList.add("火车车尾");
System.out.println(linkedList);
}
}
数组和链表的最大区别:
1.链表相比于数组不需要频繁的创造新的空间,但是两者的查找效率(get)并不相同,数组的时间复杂度为O(1)而链表的时间复杂度是O(n)
3.Vector
Vector作为原始的程序类由于其应用的广泛性,所以将其保存下来了
案例代码:
package Example1805;
import java.util.List;
import java.util.Vector;
public class javaDemo {
public static void main(String[] args) {
// 泛型<包装类>
List<Integer> all = new Vector<Integer>();
for (int i = 1;i<=10;i++){
all.add(i);
}
if (!all.isEmpty()){
System.out.println(all);
}
}
}
ArrayList与Vector的区别
ArrayList与Vector首先两者虽然外部调用方法看起来一样,但是二者的源码(内部机制)并不一样,Vector的源码中操作方法中加入了synochronized同步的操作,这就意味着多线程访问二者时候,Vector就会比较安全,但是相应的Vector的效率就会比较低
3.Set 集合 接口(常用子类 HashSet LinkedHashSet,TreeSet)
Set与List最大的不同就是,作为一个集合,有互斥性,即不能放同样的数据,或者是同样的数据会被自动覆盖掉,比如做一个统计,统计某个学校学生最喜欢的科目,100个学生但是不可能有100个科目,所以如果有学生是喜欢同样的科目就会自动覆盖。
1.Set的子类HashSet(散列集合)
注意该集合的特点是无序性,以下案例代码就可以看得出其中特性
案例代码:
package Example1806;
import java.util.HashSet;
import java.util.Set;
public class javaDemo {
public static void main(String[] args) {
Set<String> all = new HashSet<String>();
all.add("火车头");
all.add("车厢1");
// 重复数据
all.add("车尾");
all.add("车尾");
System.out.println(all);
}
}
如果想要让HashSet要按照我们顺序输入实现顺序的话就需要用到另一个兄弟类LinkedHashSet以保证其输入的有序性
2.LinkedHashSet
案例代码:
package Example1807;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Set;
public class javaDemo {
public static void main(String[] args) {
Set<String> all = new LinkedHashSet<String>();
all.add("火车头");
for (int i =1;i<=10;i++){
all.add("火车车厢"+i);
}
all.add("火车车尾");
if (!all.isEmpty()){
System.out.println(all);
}
all.clear();
}
}
3.有序集合 TreeSet
有序集合可能会跟刚才的LinkedHashSet联想在一起,实际上并不一样,其中所谓的有序指的是元素的有序性,比如集合中传入一个班级一次考试的成绩,有很大可能并不是按照考试的成绩顺序输入,那么想要实现集合内部自动排好成绩的高低。此时就需要用到TreeSet(有序集合)
案例代码1:
package Example1808;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;
public class javaDemo {
public static void main(String[] args) {
System.out.println("欢迎使用成绩等级系统");
Set<Integer> all = new TreeSet<Integer>();
Scanner scanner = new Scanner(System.in);
System.out.println("请输入需要添加的成绩(输入0时候退出系统)");
while (true){
if (scanner.hasNextInt()){
int temp = scanner.nextInt();
// 当输入的成绩位0时候退出系统
if (temp == 0){
break;
}
all.add(temp);
System.out.println("加入成绩成功");
}else {
System.out.println("您输入的成绩有问题,请重新输入");
}
}
System.out.println(all);
}
}
该代码实现了输出一个班同学所有人考试得到的成绩, 然后从低到高输出大家取到过的成绩
4.重复元素消除
问题引出:看如下代码:
package Example1809;
import java.util.HashSet;
import java.util.Set;
class Member{
private String name;
private int age;
private int id;
Member(String name,int age,int id){
this.age = age;
this.name = name;
this.id = id;
}
@Override
public String toString() {
return "Member{" +
"name='" + name + '\'' +
", age=" + age +
", id=" + id +
'}';
}
}
public class javaDemo {
public static void main(String[] args) {
Set<Member> all = new HashSet<Member>();
// 重复对象
all.add(new Member("赵五",20,001));
all.add(new Member("赵五",20,001));
System.out.println(all);
}
}
问:按理来说,add的两个对象其实都是同一个人,如果定义集合Set就应该剔除重复对象,为什么没有剔除呢?
虽然添加了两个具有相同数据的Member对象,但它们在内存中的地址不同,因此HashSet无法识别它们是相同的对象,也就无法将其视为重复元素进行删除。
要使HashSet正确识别重复的Member对象,需要在Member类中重写hashCode()和equals()方法,以便根据实际的业务逻辑来判断对象是否重复。例如,可以根据name、age和id属性来判断两个Member对象是否相同。重写这两个方法后,HashSet就能正确地剔除重复对象。
重复元素消除实现案例代码;
package Example1809;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
class Member{
private String name;
private int age;
private int id;
Member(String name,int age,int id){
this.age = age;
this.name = name;
this.id = id;
}
@Override
public boolean equals(Object o) {
// 如果存放的内存地址一样。那么自然就是一样的
if (this == o){
return true;
};
// 检查类型是否相同
if (o instanceof Member){
Member other = (Member) o;
// 判断所有值是否相同
return Objects.equals(this.name,other.name)&&this.age == other.age&&this.id == other.id;
}
return false;
}
@Override
public int hashCode() {
// 根据name,age,id计算哈希值
return Objects.hash(name, age, id);
}
@Override
public String toString() {
return "Member{" +
"name='" + name + '\'' +
", age=" + age +
", id=" + id +
'}';
}
}
public class javaDemo {
public static void main(String[] args) {
Set<Member> all = new HashSet<Member>();
// 重复对象
all.add(new Member("赵五",20,001));
all.add(new Member("赵五",20,001));
System.out.println(all);
}
}
可以看到同样的对象消失了,这样就算实现了重复元素的消除
4.集合输出(迭代器Iterator , Enumeration )
1.迭代器iterator(集合的标准输出)
在前面的Collection中定义的方法
iterator() | 返回集合的迭代器 | public | 无 | Iterator<E> |
这一段说明实现集合都可以通过迭代器iterator输出,其创建的实例方法流程是
Iterator iterator = 某个集合.iterator
Iterator接口的常用方法
方法名 | 描述 | 方法修饰符 | 参数 | 返回类型 |
---|---|---|---|---|
hasNext() | 检查迭代器是否还有下一个元素。如果有,则返回true;否则返回false。 | public | 无 | boolean |
next() | 返回迭代器的下一个元素,并将迭代器的位置指向下一个元素。 | public | 无 | E |
remove() | 从迭代器所在的集合中移除迭代器返回的最后一个元素(可选操作)。 | public | 无 | void |
案例代码;
package Example1803;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
class Person{
private String name;
private int age;
Person(String name,int age){
this.age =age;
this.name = name;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
}
public class javaDemo {
public static void main(String[] args) {
List<Person> personList = new ArrayList<Person>();
personList.add(new Person("黄小龙",87));
personList.add(new Person("陈非凡",20));
personList.add(new Person("陈俊",20));
// 直接输出会输出类的地址
System.out.println(personList);
// 通过迭代器遍历输出对象的名称和age
Iterator<Person> iterator = personList.iterator();
while (iterator.hasNext()){
// 需要有对象接收不能直接输出iterator.next.getName()+iterator.next.getAge
// 这样会出现错误,因为iterator接收数据后立刻就往下走
Person person = iterator.next();
System.out.println(person.getName()+"的年龄是"+person.getAge());
}
}
}
熟悉集合类型与Iterator的实现
package Example1810;
import java.util.*;
public class javaDemo {
public static void main(String[] args) {
// 链表
List<String> list1 = new LinkedList<String>();
list1.add("和平号高铁车头");
list1.add("和平号高铁车厢");
list1.add("和平号高铁车尾");
Iterator<String> iterator1 = list1.iterator();
while (iterator1.hasNext()){
System.out.println(iterator1.next());
}
// 散列集合
Set<String> set1 = new HashSet<String>();
set1.add("绿皮火车车头");
set1.add("绿皮火车车厢");
set1.add("绿皮火车车尾");
Iterator<String> iterator2 = set1.iterator();
while (iterator2.hasNext()){
System.out.println(iterator2.next());
}
// 有序集合
Set<Integer> set2 = new TreeSet<Integer>();
set2.add(1);
set2.add(2);
set2.add(3);
Iterator<Integer> iterator3 = set2.iterator();
while (iterator3.hasNext()){
System.out.println(iterator3.next());
}
}
}
2.Enumeration
Enumeration该接口与Vector都是原始接口都是在jdk很早前就定义了,该接口主要是用于对Vector的数据输出,在JDK1.5后对其进使用了泛型重新修改
该接口有两个比较常用的方法:
方法名 | 描述 |
---|---|
hasMoreElements() | 检查枚举对象是否有更多的元素可供迭代。如果有,则返回true;否则返回false。 |
nextElement() | 返回枚举对象的下一个元素,并将枚举对象的位置指向下一个元素。如果没有更多元素,则会抛出NoSuchElementException异常 |
案例代码:
package Example1811;
import java.util.Enumeration;
import java.util.Vector;
public class javaDemo {
public static void main(String[] args) {
Vector<String> vector = new Vector<>();
vector.add("测试1");
vector.add("测试2");
vector.add("测试3");
// 通过vector的elements实例化
Enumeration<String> enumeration = vector.elements();
while (enumeration.hasMoreElements()){
System.out.println(enumeration.nextElement());
}
}
}