Collection
Collection【接口】:
我们通过帮助文档发现,Collection是一个接口,不能直接new对象
根据元素是否可以发生重复,继续分类
- List【接口】 元素有序,可以发生重复,有索引的概念
ArrayList 底层数据结构是数组,查询快,增删慢,线程不安全,效率高。
Vector[具体的子类]: 底层数据结构是数组,查询快,增删慢,先出安全,效率低。
即便Vector是线程安全的,我们以后也不会用它。
LinkedList[具体的子类]: 底层数据结构是双链表,增删快,查询慢,线程不安全,效率高
- Set【接口】 元素无序且唯一,没有索引
HashSet: 底层数据结构是哈希表,查找速度快,且元素唯一
TreeSet: 底层数据结构是红黑树(自平衡二叉树),具备了可预测的排序
- 自然排序
- 比较器排序
借助ArrayList子类对象来使用Collection接口中的方法
学习java中任意一个集合的步骤:
1、创建相关集合对象
2、创建元素对象
3、将元素添加到集合中
4、遍历集合
Collection中的成员方法:
boolean add(E e)
boolean remove(Object o)
void clear()
boolean contains(Object o)
boolean isEmpty()
int size()
点击查看代码
public class CollectionDemo1 {
public static void main(String[] args) {
//借助ArrayList创建对象来使用Collection接口中的方法
// 1、创建相关集合对象
Collection c1 = new ArrayList();
//boolean add(Object e)
c1.add(100); //这里涉及到自动装箱 int -> Integer
c1.add(true);
c1.add(12.34);
c1.add(1000L);
c1.add(100);
c1.add(12.34);
// 重写toString()方法的类是ArrayList类的父类的父类中重写的。
// 底层是使用StringBuilder实现的
System.out.println("c1: " + c1);
//注意:我们今后使用集合的时候,规定一个集合只能存储一种数据类型的元素
System.out.println("-----------------------------------------");
//[100, true, 12.34, 1000, 100, 12.34]
//boolean remove(Object o) 从集合中删除一个元素,只会删除最左边的一个匹配元素
c1.remove(100);
System.out.println("c1: " + c1);
System.out.println("-----------------------------------------");
//void clear() 清空集合元素
// c1.clear();
// System.out.println("c1: " + c1);
System.out.println("-----------------------------------------");
//boolean contains(Object o) 判断Collection集合中是否包含某个元素
System.out.println(c1.contains(12.34));
System.out.println("-----------------------------------------");
//boolean isEmpty() 判断Collection集合是否为空
System.out.println(c1.isEmpty());
System.out.println("-----------------------------------------");
//int size() 获取集合的长度【元素的个数】
System.out.println(c1.size());
}
}
boolean addAll(Collection c)
boolean removeAll(Collection c)
boolean containsAll(Collection c)
boolean retainAll(Collection c)
点击查看代码
public class CollectionDemo2 {
public static void main(String[] args) {
Collection c1 = new ArrayList();
c1.add("你");
c1.add("好");
c1.add("世");
c1.add("界");
c1.add("hello");
c1.add("world");
Collection c2 = new ArrayList();
c2.add("hello");
c2.add("world");
c2.add(1111);
System.out.println("c1="+ c1);
System.out.println("c2="+c2);
System.out.println("==============");
c1.addAll(c2);//c1元素拼接上c2 c2不变
// System.out.println(c1);
// System.out.println(c2);
// System.out.println("==============");
c1.removeAll(c2); // 删除c1中所有的c2元素,c2不变
System.out.println(c1);
System.out.println(c2);
// System.out.println("==============");
System.out.println(c1.containsAll(c2));//c1是否包含c2的所有
System.out.println("================");
//boolean retainAll(Collection c) 求交集
c1.retainAll(c2);
System.out.println("c1"+c1);
System.out.println("c2"+c2);
}
}
如何遍历一个Collection集合
1、Object[] toArray() 把集合转成数组,可以实现集合的遍历
点击查看代码
public class CollectionDemo3 {
public static void main(String[] args) {
ArrayList<String> c1 = new ArrayList<>();
c1.add("hello");
c1.add("world");
c1.add("java");
c1.add("hadoop");
c1.add("world");
// Object[] o = c1.toArray();
//for(int i = 0;i< o.length;i++){
// Object o1 = o[i];
// String s2 = (String) o1;
// System.out.println(s2+"--"+s2.length());
for (String s : c1) {
System.out.println(s+"--"+s.length());
}
}
}
Iterator iterator() 迭代器,集合的专用遍历方式
点击查看代码
public class CollectionDemo4 {
public static void main(String[] args) {
Collection list = new ArrayList();//泛型(规范形式)只能用一种特定形式
list.add("王骏");//对象名.add()向list集合里添加元素
list.add("李娜");
list.add(13.14);
list.add(520);
list.add("ln");
Iterator iterator = list.iterator();
while(iterator.hasNext()){
Object it = iterator.next();
String s = (String) it;
System.out.println(it+"--"+it.toString().length());//将集合中的元素转换成字符串类型在去求他的长度
}
}
}
Collection集合存储自定义对象
1、创建集合对象
2、创建元素对象
3、将元素添加到集合中
4、遍历集合
创建一个student类
点击查看代码
public class Student {
private String name;
private int age;
public Student(){}
public Student(String name,int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
点击查看代码
public class CollectionDemo5 {
public static void main(String[] args) {
ArrayList<Student>list= new ArrayList<>();
Student s1 = new Student("王骏", 18);
Student s2 = new Student("李娜", 21);
Student s3 = new Student("王小贱", 19);
list.add(s1);
list.add(s2);
list.add(s3);
Iterator<Student> iterator = list.iterator();
while(iterator.hasNext()){
Student it = iterator.next();
System.out.println(it.getName()+"-"+it.getAge());
}
}
}
List集合:元素可以发生重复,有序(指存储和取出的顺序一致)
Collection【接口】:
- List【接口】
ArrayList
- Set【接口】
List集合中特有的成员方法:
void add(int index,E element)
E remove(int index)
E get(int index)
E set(int index,E element)
ListIterator listIterator()
点击查看代码
public class ListDemo1 {
public static void main(String[] args) {
List<Teacher> list = new ArrayList<>();
Teacher t1 = new Teacher("张三", 21, "男");
Teacher t2 = new Teacher("张大", 37, "女");
Teacher t3 = new Teacher("张狼", 34, "男");
list.add(t1);
list.add(t2);
list.add(t3);
System.out.println(list);
// void add(int index,E element) 向指定位置添加元素,新添加的在集合的对应索引上
list.add(2,new Teacher("李真狗",23,"男"));
System.out.println(list);
// E remove(int index) 删除对应索引上的数据
list.remove(3);
System.out.println(list);
// E get(int index) 获取对应索引上的数据
System.out.println(list.get(0));
// E set(int index,E element) 更改特定索引上的数
System.out.println(list.set(0, new Teacher("王骏", 12, "男")));
//将王骏改成李娜
list.get(0).setName("李娜");
System.out.println(list);
ListIterator<Teacher> listIterator = list.listIterator();
while(listIterator.hasNext()){
Teacher t = listIterator.next();
System.out.println("姓名:"+t.getName()+"\t\t" + "年龄:"+ t.getAge()+"\t\t"+"性别:"+t.getSex());
}
}
}
遍历集合
点击查看代码
public class ArrayListDemo1 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();//泛型(规范形式)只能用一种特定形式
list.add("王骏");//对象名.add()向list集合里添加元素
list.add("李娜");
list.add("love");
list.add("you");
list.add("ln");
//方式一:将list集合转换为数组形式在进行for循环进行遍历
System.out.println("将list集合转换为数组形式在进行for循环进行遍历");
Object[] o = list.toArray();
for (int i = 0; i < o.length; i++) {
System.out.println(o[i]+"--"+list.get(i).length());
}
System.out.println("方式二:迭代器进行遍历");
//方式二:迭代器进行遍历
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
String s = iterator.next();
System.out.println(s+"--"+s.toString().length());
}
System.out.println("方式三:对list集合进行for循环进行遍历");
//方式三:对list集合进行for循环进行遍历
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i)+"=="+list.get(i).length());
}
System.out.println("方式四:这是强化for循环");
System.out.println("这是强化for循环");
for (String s : list) {
System.out.println(s+"--"+s.length());
}
}
}
去除集合中自定义对象的重复值(对象的成员变量值都相同)
我们要去看contains的源码,底层判断元素是否存在新集合的逻辑是:
挨个使用待插入的元素与新集合中的元素使用equals方法比较,我们元素Student类中并没有重写equals方法
所以使用的是父类Object中的equals方法,而父类Object中的equals方法比较的是地址值
又因为每一个学生都是new出来的,所以地址值都不一样,比较的结果永远为false
要想比较内容值,需要元素类型重写equals方法,自动生成即可
重写equals方法
@Override
public boolean equals(Object o) {//需要重写equals方法,才可以进行比较
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name);
}
实现去重
点击查看代码
public class ArrayListDemo2 {
public static void main(String[] args) {
ArrayList<Student> list1 = new ArrayList<>();
list1.add(new Student("王骏", 17));
list1.add(new Student("李娜", 21));
list1.add(new Student("门金锁", 22));
list1.add(new Student("李娜", 21));
list1.add(new Student("王骏", 17));
System.out.println(list1);
ArrayList<Student> list2 = new ArrayList<>();//需要创建一个集合来接收
for (int i = 0; i < list1.size(); i++) {
Student student = list1.get(i);
if (!list2.contains(student)) {//如果我们的新集合里不包含这个学生信息,那么就往集合里面添加
list2.add(student);
}
}
System.out.println(list2);
}
}
获取10个1-20之间的随机数,要求不能重复
点击查看代码
public class ListTest1 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();//确保集合元素的类型
while(list.size()<10){
int i = new Random().nextInt(10) + 1;
if(!list.contains(i)){
list.add(i);
}
}
System.out.println(list);
}
}
键盘录入多个数据,以0结束,要求在控制台输出这多个数据中的最大值
点击查看代码
public class ListDemo2 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
while(true){
System.out.println("请输入int类型的数据:");
int number = new Scanner(System.in).nextInt();
if(number==0){
break;
}else{
list.add(number);
}
}
Integer max = list.get(0);
for (int i = 1; i < list.size(); i++) {
if(list.get(i)>max){
max = list.get(i);
}
}
System.out.println(max);
}
}
Vector[具体的子类]: 底层数据结构是数组,查询快,增删慢,先出安全,效率低。
即便Vector是线程安全的,我们以后也不会用它。
特殊的功能:
public void addElement(E obj)
public E elementAt(int index)
public Enumeration elements()
点击查看代码
public class VectorDemo1 {
public static void main(String[] args) {
//创建Vector集合对象
Vector v1 = new Vector();
//创建元素并添加元素
v1.add("hello");
v1.add("world");
v1.add("java");
v1.add("hadoop");
v1.add("hbase");
v1.add("java");
v1.add("hello");
System.out.println("v1: "+v1);
System.out.println("-------------------------------");
//public void addElement(Object obj) 向集合中添加元素
// v1.addElement("flink");
// System.out.println("v1: "+v1); // 效果和add方法一模一样,可以使用add方法替代
//public Object elementAt(int index) 根据索引获取元素
// System.out.println(v1.elementAt(2));// 效果和get方法一模一样,可以使用get方法替代
// System.out.println(v1.get(2));
//public Enumeration elements()
// Enumeration elements = v1.elements();// 效果和迭代器方法一模一样,可以使用迭代器方法替代
// while (elements.hasMoreElements()){
// System.out.println(elements.nextElement());
// }
}
}
LinkedList[具体的子类]: 底层数据结构是双链表,增删快,查询慢,线程不安全,效率高
特殊功能:
public void addFirst(E e)及addLast(E e)
public E getFirst()及getLast()
public E removeFirst()及public E removeLast()
点击查看代码
import java.util.LinkedList;
public class LinkedListDemo1 {
public static void main(String[] args) {
LinkedList<String> list = new LinkedList<>();
list.add("wangjun");
list.add("王骏");
list.add("李娜");
list.add("lina");
System.out.println(list);
// public void addFirst(E e)及addLast(E e)
list.addFirst("王");
list.addLast("李");
System.out.println(list);
//public E getFirst()及getLast()
System.out.println(list.getFirst());
System.out.println(list.getLast());
System.out.println(list);
//public E removeFirst()及public E removeLast()
System.out.println(list.removeFirst());
System.out.println(list.removeLast());
System.out.println(list);
}
}
LinkedList
请用LinkedList模拟栈数据结构的集合,并测试
题目的本意是,自己写一个类,底层封装了LinkedList,创建这个类,把这个类当作集合类去用。
先自己创建一个MyLinkedList类
点击查看代码
public class MyLinkedList {
LinkedList linkedlist = new LinkedList();
MyLinkedList(){}
public void addYuanSu(Object o){ //创建添加元素的方法
linkedlist.addFirst(o);
}
public Object getYuanSu(){ // 创建获取元素的方法
return linkedlist.removeFirst();
}
public int getLength(){//获取他的长度
return linkedlist.size();
}
@Override
public String toString() {
return "linkedlist=" + linkedlist;
}
}
创建测试类
点击查看代码
public class LinkedListTest1 {//我们只能调用我们创建类中的方法,别的方法不行
public static void main(String[] args) {
MyLinkedList list = new MyLinkedList();
//模拟栈数据结构的集:先进后出
list.addYuanSu("我");
list.addYuanSu("爱");
list.addYuanSu("你");
list.addYuanSu("新");
list.addYuanSu("中");
list.addYuanSu("国");
System.out.println(list.toString());
int length = list.getLength();
for (int i = 0; i < length; i++) {
System.out.println(list.getYuanSu());
}
}
}
HashSet中的add方法实际上调用的是HashMap中的put方法
底层和元素的hashCode方法值有关
我们发现,底层判断待插入的元素是否已经存在哈希表中的方式是:
将待插入的元素的哈希值与已经存储在哈希表中元素哈希值进行比较,
然后再调用待插入的元素的equals方法比较已经存储在哈希表中元素。
若哈希值一样,且equals结果为true,就表示这两个元素是同一个元素,不做添加
结论:
若想要使用HashSet对元素进行去重,需要元素类型本身重写hashCode方法和equals方法。
对非元素 进行去重无需做其他操作
点击查看代码
public class HashSetDemo1 {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("hello");
set.add("world");
set.add("hello");
set.add("wangjun");
set.add("lina");
System.out.println(set);//set集合里无需自己做操作自己将会去重
}
}
使用HashSet对元素进行去重,
创建student类,重写hashCode方法和equals方法
@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 && Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
测试类
点击查看代码
public class HashSetDemo2 {
public static void main(String[] args) {
HashSet<Student> set = new HashSet<>();
set.add(new Student("王骏",21));
set.add(new Student("李娜",22));
set.add(new Student("王骏",21));
set.add(new Student("王小贱",31));
System.out.println(set);
}
}
TreeSet: 底层数据结构是红黑树(自平衡二叉树),具备了可预测的排序
- 自然排序
- 比较器排序
TreeSet中的add方法实际上是调用了TreeMap中的put方法
`使用TreeSet集合存储字符串元素 //实现去重和排序`
<details>
<summary>点击查看代码</summary>
public class TreeSet {
public static void main(String[] args) {
java.util.TreeSet<String> set = new java.util.TreeSet<>();
set.add("ai");
set.add("cat");
set.add("dog");
set.add("mouse");
set.add("ai");
System.out.println(set);
}
}
要想使用TreeSet集合存储自定义对象且使用的是无参构造方法创建TreeSet集合对象的话,
需要元素类型实现Comparable<元素类型>接口,实现compareTo方法(必须要顶下Comparable的元素类型,不然无法进行比较)
compareTo方法根据需求来定制
创建工人类
点击查看代码
public class Worker implements Comparable<Worker>{//实现Comparable接口泛型为(Worker)为下面重写compareTo方法做准备
//如果使用Object 范围太大找不到Worker的age和name
private String name;
private int age;
private String sex;
public Worker(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public Worker() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Worker{" +
"name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
'}';
}
@Override
public int compareTo(Worker w) {//年龄需要从小到大排序
int i = this.age - w.getAge();// 满足this - w 是从小到大 ,w - this 是从大到小
return (i==0)?this.name.compareTo(w.getName()):i;
}
}
创建测试类
点击查看代码
public class TreeSetDemo2 {
public static void main(String[] args) {
TreeSet<Worker> set = new TreeSet<>();
set.add(new Worker("王骏",43,"男"));
set.add(new Worker("王小建",23,"男"));
set.add(new Worker("李娜",21,"女"));
set.add(new Worker("琳娜那",24,"女"));
set.add(new Worker("王骏",43,"男"));
System.out.println(set);
}
}
使用里匿名内部类进行排序
需求:
把狗狗的年龄进行从大到小进行排序,并且将他们的名字改成老大,老二,老三,老四
点击查看代码
//把狗狗的年龄进行从大到小进行排序,并且将他们的名字改成老大,老二,老三,老四
public class TreeSetDemo3 {
public static void main(String[] args) {
TreeSet<Dog> set = new TreeSet<>(new Comparator<Dog>() {//匿名内部类
@Override
public int compare(Dog o1, Dog o2) {
int i = o2.getAge() - o1.getAge();//排序为从大到小
return (i == 0) ? o2.getName().compareTo(o1.getName()) : i;
}
});
set.add(new Dog("大黄",2));
set.add(new Dog("jack",4));
set.add(new Dog("张三",1));
set.add(new Dog("小吉",5));
set.add(new Dog("jack",4));
System.out.println(set);
ArrayList<Dog> list = new ArrayList<>();
Iterator<Dog> iterator = set.iterator();
while(iterator.hasNext()){
Dog d = iterator.next();
if(!list.contains(d)){
list.add(d);
}
}
System.out.println(list);
list.get(0).setName("老大");
for (int i = 0; i < list.size(); i++) {
switch (i){
case 0:
list.get(i).setName("老大");
break;
case 1:
list.get(i).setName("老二");
break;
case 2:
list.get(i).setName("老三");
break;
case 3:
list.get(i).setName("老四");
break;
}
}
System.out.println(list);
}
}
键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低输出到控制台
点击查看代码
public class TreeSetTest1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//创建一个TreeSet集合
TreeSet<Student2> set1 = new TreeSet<>(new Comparator<Student2>() {
@Override
public int compare(Student2 o1, Student2 o2) {
//显式条件:按照总分从高到低输出到控制台
int i1 = o2.getSumScore() - o1.getSumScore();
//隐式条件
//总分一样,语文成绩不一定一样
int i2 = (i1 == 0) ? o2.getChinese() - o1.getChinese() : i1;
//总分一样,语文成绩一样,数学成绩不一定一样
int i3 = (i2 == 0) ? o2.getMath() - o1.getMath() : i2;
//各科成绩一样,姓名不一定一样
return (i3 == 0) ? o2.getName().compareTo(o1.getName()) : i3;
}
});
for(int i=1;i<=5;i++){
System.out.println("请输入第 "+i+" 个学生的信息");
System.out.print("请输入姓名: ");
String name = sc.next();
System.out.print("请输入该学生的语文成绩: ");
int chinese = sc.nextInt();
System.out.print("请输入该学生的数学成绩: ");
int math = sc.nextInt();
System.out.print("请输入该学生的英语成绩: ");
int english = sc.nextInt();
set1.add(new Student2(name,chinese,math,english));
}
System.out.println("学生信息录入完毕!!");
System.out.println("================= 学生成绩汇总 ===================");
System.out.println("姓名\t\t语文成绩\t\t数学成绩\t\t英语成绩\t\t总分");
//遍历集合
for (Student2 student2 : set1) {
System.out.println(student2.getName()+"\t\t"+
student2.getChinese()+"\t\t"+
student2.getMath()+"\t\t"+
student2.getEnglish()+"\t\t"+
student2.getSumScore());
}
}
}

浙公网安备 33010602011771号