集合:
为什么需要集合,存储数据用数组不就行了吗?
对于对象数据据进行排序 ?
以及对重复数据进行去重 ?
以及存储对应的 Key Value 数据?
集合作为应该容器,内部提供了一些类,可以为存储在内的大批量数据提供对应的对象方法
哪些类是集合类?对应方法如何使用?
集合中的类:
1. Collection顶级父接口
java
/*
TODO 查看顶级父接口 Collection 的方法
1.add
用于添加一个Object子类的元素,其中对于基本数据类型并不是 Object子类 但是可以添加(添加后会对其装箱)
2.toArray
3.remove
4.clear
补:
<>:表示泛型,用于限制当前集合存储数据的类型,暂时可以不用给定
对于数据相关的类,一般先做增删改查,之后再看其特殊方法
对于Collection并没有提供针对单个元素的获取以及修改方法?
对于不同的子实现类,其特性不一样 比如 List 和 Set 来说 List有序,Set是无序
那么Set不能通过其下标去取数据,Collection 仅仅是一个接口,具体实现要看其子实现对象
*/
// 由于Collection为接口无法实例化对象,
// 而ArrayList为实现该接口的实体类。由于Java中的多态思想:父类的引用指向子类实例。
// 因此,可以这样来实例化对象,用其调用方法。
Collection collection = new ArrayList();
collection.add("1");
collection.add(1);
collection.add(true);
int i = 2;
// add()方法会对基本数据类型进行自动装箱 包装成 Integer
collection.add(i);
System.out.println(collection);
/*
collection 提供的iterator()方法可以获取其数据
*/
collection.iterator();
// toArray() 将数据转换成一个数组,因此转换后可以对其进行数组的操作
System.out.println(collection.toArray()[0]);
for (Object o : collection) {
System.out.println(o);
}
/*
删除数据
*/
collection.remove(true);
System.out.println(collection);
collection.clear();
System.out.println(collection);
2.迭代器
java
/*
TODO 通过Collection获取其迭代器
迭代器是用于遍历数据的一种容器 迭代器维护了一个指针,其指针一开始位置在集合之前
其提供的方法:
hasNext:查看当前位置是否存在数据
next: 获取下一个位置的数据 将当前指针移动下一个,然后返回当前指针指向的数据
*/
java
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class DemoIterator {
public static void main(String[] args) {
/* TODO
collection.iterator() 方法的调用
对于ArrayList中iterator方法返回了一个Itr对象
new Itr();
// Itr类为ArrayList的成员内部类 并且是属于私有的 private 私有的只能在当前 ArrayList类中使用
// 所以可以 new一个对象 并且实现了 Iterator 接口
private class Itr implements Iterator<E> {
// cursor 游标; 指针
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification(); //
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
// Object数组
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
// 对游标进行移动1位
cursor = i + 1;
// 获取当前i的下标数据
return (E) elementData[lastRet = i];
}
}
*/
Collection collection = new ArrayList();
Iterator iterator = collection.iterator(); // iterator => Collection 是抽象的
int i = 1;
Integer integer = i;
//integer1指向创建的对象的地址
Integer integer1 = new Integer(i);
// TODO
// Integer valueOf(int i):返回一个表示指定的 int 值的 Integer 实例。
// Integer valueOf(String s):返回保存指定的 String 的值的 Integer 对象。
// Integer valueOf(String s, int radix):
// 返回一个 Integer 对象,该对象中保存了用第二个参数提供的基数进行解析时从指定的 String 中提取的值。
Integer integer2 = Integer.valueOf(i);
System.out.println(integer == integer1); // false
System.out.println(integer == integer2); // true
}
}
3. Collection实现实例
java
import java.util.ArrayList;
import java.util.Collection;
public class StudentCollection {
public static void main(String[] args) {
Collection arrayList = new ArrayList();
arrayList.add(new Student("陆玉龙", 18, "bigdata30"));
arrayList.add(new Student("汪雨", 19, "bigdata30"));
arrayList.add(new Teacher("杨德广", 28, "bigdata30"));
for (Object o : arrayList) {
// com.shujia.day08.Student cannot be cast to com.shujia.day08.Teacher
// 测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型,是则返回True。
if (o instanceof Teacher) {
//若不对集合添加泛型,默认传入的对象是Object类型对象,o为Object类型对象,要将其进行强制类型转换
Teacher o1 = (Teacher) o;
System.out.println(o1);// Student{name='陆玉龙', age=18, clazz='bigdata30'}
o1.teach();
} else if (o instanceof Student) {
Student o1 = (Student) o;
System.out.println(o1);
o1.learn();
}else {
System.out.println(o);
}
}
/*
对于上述的调用过程,有时会出现类型转换问题,那么如何解决?
1.获取对象对其进行判断是否为某个类的对象或子类对象 如果是那么进行强制类型转换 再进行调用
2.由于Java是强类型语言,对于一个集合一般情况下,都只存储一种类型的数据
为了对其进行限制,提供了泛型方式
*/
// class ArrayList<E> => 其中<E> 表示泛型类型,给定的类型需要继承Object 引用类型
// E 表示当前集合中存储的所有元素的类型 为 E
Collection<Student> students = new ArrayList<>();
students.add(new Student("汪雨", 19, "bigdata30"));
students.add(new Student("许康杰", 29, "bigdata30"));
//TODO 报错:泛型确定了集合中数据的类型 students.add(new Teacher("许康杰", 29, "bigdata30"));
System.out.println(students);
// 对于取到的每个元素的类型就可以确定
for (Student student : students) {
System.out.println(student);
student.learn();
}
// Collection<int> ints = new ArrayList<>();
Collection<Integer> ints = new ArrayList<>(); // 对于基本数据类型需要使用其包装类
// 对于泛型E 满足多态 => 父类引用指向子类对象
Collection<Person> peoples = new ArrayList<>();
peoples.add(new Student("汪雨", 19, "bigdata30"));
System.out.println(peoples);
// for (Person people : peoples) {
//
// }
}
}
class Teacher {
String name;
int age;
String clazz;
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 getClazz() {
return clazz;
}
public void setClazz(String clazz) {
this.clazz = clazz;
}
public Teacher(String name, int age, String clazz) {
this.name = name;
this.age = age;
this.clazz = clazz;
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", age=" + age +
", clazz='" + clazz + '\'' +
'}';
}
public void teach() {
System.out.println(name + "老师" + "正在教授大数据..");
}
}
class Person{
}
class Student extends Person{
String name;
int age;
String clazz;
public Student(String name, int age, String clazz) {
this.name = name;
this.age = age;
this.clazz = clazz;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", clazz='" + clazz + '\'' +
'}';
}
public void learn() {
System.out.println(name+"同学正在学习Java");
}
}
4.继承自Collection接口的List接口
java
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class DemoList {
public static void main(String[] args) {
/*
TODO List 接口的用法
有序集合(也称为序列 )。 用户可以精确控制列表中每个元素的插入位置。
用户可以通过整数索引(列表中的位置)访问元素,并搜索列表中的元素。
通过下标的方式来维护存储的数据位置
*/
List<Integer> integers = new ArrayList<>();
// 对于集合Collection不能指定获取单个元素,但是由于List接口其特性已经确定,所以可以获取
integers.add(3);
integers.add(5);
integers.add(6);
integers.add(2);
integers.add(1);
integers.add(7);
integers.add(8);
integers.add(4);
integers.add(9);
System.out.println(integers.get(0)); // 1
// System.out.println(integers[1]); // 1 => []获取数据只能通过数组
System.out.println(integers.indexOf(4)); // 获取元素所在的下标位置
integers.remove(1);
System.out.println(integers);
// set要求传入下标和元素
integers.set(1,5);
System.out.println(integers);
// 遍历数据
//方法一
for (Integer integer : integers) {
System.out.println("elem:"+integer);
}
//方法二
for (int i = 0; i < integers.size(); i++) {
System.out.println("index elem:"+integers.get(i));
}
/*
TODO List集合迭代器:
hasPrevious:查看指针上一个有没有数据
previous:将指针进行上移,并获取其中的数据
hasNext:查看当前位置是否存在数据
next: 获取下一个位置的数据 将当前指针移动下一个,然后返回当前指针指向的数据
*/
ListIterator<Integer> integerListIterator = integers.listIterator();
while (integerListIterator.hasNext()){
System.out.println(integerListIterator.next());
}
while (integerListIterator.hasPrevious()){
System.out.println(integerListIterator.previous());
}
}
}
5. List中Remove方法
java
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class ListRemove {
public static void main(String[] args) {
/*
对于自定义类使用List中的方法
*/
List<Stu> stus = new ArrayList<>();
Stu stu = new Stu("陆玉龙", 18, "bigdata30");
stus.add(stu);
stus.add(new Stu("徐玉娟",18,"bigdata30"));
/*
TODO remove的源码:
public boolean remove(Object o) {
// 对象等于null
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
// 不为null
for (int index = 0; index < size; index++)
// 遍历 elementData中所有的数据 并使用equals方法对其进行比较
//TODO 由于当前Stu没有重写equals方法,所以使用的是Object中继承的 默认使用 == 判断
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
*/
//TODO 由于重写了equals()方法,导致进行remove(stu)时判断前两个添加的元素都符合条件,
// 因此将它们都给删除了
stus.remove(stu);
stus.remove(new Stu("徐玉娟",18,"bigdata30"));
System.out.println(stus);
}
}
class Stu{
String name;
int age;
String clazz;
public Stu(String name, int age, String clazz) {
this.name = name;
this.age = age;
this.clazz = clazz;
}
@Override
public String toString() {
return "Stu{" +
"name='" + name + '\'' +
", age=" + age +
", clazz='" + clazz + '\'' +
'}';
}
// TODO: 重写继承自Object类中的equals()方法,
// 因为Object类中的equals()方法比较的是两个元素的存储地址,不满足我们现在实际的需要
// 重写后通过比较两个对象的属性值来判断它们是否相同
@Override
public boolean equals(Object o) {
//返回 true 或 false
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Stu stu = (Stu) o;
return age == stu.age && Objects.equals(name, stu.name) && Objects.equals(clazz, stu.clazz);
}
@Override
public int hashCode() {
return Objects.hash(name, age, clazz);
}
}
6. List中Sort方法与Arrays中Sort方法的使用
java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class ListSort {
public static void main(String[] args) {
/*
TODO 排序操作:
1. List中的排序,可以使用 List对象的sort方法
需要传入一个 Comparator 实例对象 要实现其 compare 方法 第一个值减去第二个值就是升序 否则就是降序
或者对于基本数据类型包装类 传入 null 即可
2.Arrays对自定义类数组的排序
Arrays类位于 java.util 包中,主要包含了操作数组的各种方法。
需要对自定义类实现 Comparable 接口,并实现其 compareTo方法
当前对象减去传入的对象 就是升序 反之降序
*/
List<Integer> integers = new ArrayList<>();
integers.add(3);
integers.add(5);
integers.add(6);
integers.add(2);
integers.add(1);
integers.add(7);
integers.add(8);
integers.add(4);
integers.add(9);
/*
sort方法需要传入 Comparator<? super E> c 参数
排序需要给定规则,规则是由 Comparator 的实现对象决定的
而 interface Comparator<T> 为一个接口 => 不能构建具体的对象
方式1:可以创建一个类 实现该接口,并创建实现类对象传给 sort
方式2:匿名内部类实现
方式3:对于基本类型数据的包装类,做排序时,可以直接传入null值
*/
// 方式1:可以创建一个类 实现该接口,并创建实现类对象传给 sort
integers.sort(new IntSort());
//方式2:匿名内部类实现
integers.sort(new Comparator<Integer>() {
@Override
public int compare(Integer thisObj, Integer otherObj) {
return -(thisObj - otherObj);
}
});
// 方式3:对于基本类型数据的包装类,做排序时,可以直接传入null值
integers.sort(null);
System.out.println(integers);
String[] allStr = new String[3];
allStr[0] = "10";
allStr[1] = "8";
allStr[2] = "1";
Arrays.sort(allStr);
// Arrays.sort() 底层代码默认是按照字典顺序比较
System.out.println(Arrays.toString(allStr));
//区别与 Tea tees1 = new Tea(); 写法,以数组形式呈现
Tea[] teas = new Tea[3];
teas[0] = new Tea("张三",19,3);
teas[1] = new Tea("李四",19,4);
teas[2] = new Tea("王五",21,4);
/*
java.lang.ClassCastException: com.shujia.day08.Tea cannot be cast to java.lang.Comparable
类型转换错误 => 给定的是自定义对象, Arrays并不知道具体的排序方式
现在底层代码是将 每个Tea对象强制类型 转换成 Comparable 对象 并调用其 compareTo 方法 ,默认使用字典排序
现在 interface Comparable 是一个接口 实现其 compareTo
*/
Arrays.sort(teas);
System.out.println(Arrays.toString(teas));
}
}
// TODO Comparator<T> 其中T表示要比较的数据类型
// Comparator<T> 与 Comparable<T> 的区别???
class IntSort implements Comparator<Integer>{
//不符合实现情况中的判断逻辑,因此对compare()方法进行重写
@Override
public int compare(Integer thisObj, Integer otherObj) {
/*
thisObj - otherObj 是自然升序的方式进行排序
*/
return -(thisObj - otherObj); //是自然降序的方式进行排序
}
}
class Tea implements Comparable<Tea>{
String name;
int age;
int year;
public Tea(String name, int age, int year) {
this.name = name;
this.age = age;
this.year = year;
}
//不符合实现情况中的判断逻辑,compareTo()方法进行重写
@Override
public int compareTo(Tea other) {
/*
定义两个对象的比较逻辑:
1.先比较工作年限 年限相同再比较年龄
*/
// 年限相减结果为 0 表示相同
int compareRes = this.year - other.year == 0 ? this.age - other.age : this.year - other.year;
return - compareRes;
}
@Override
public String toString() {
return "Tea{" +
"name='" + name + '\'' +
", age=" + age +
", year=" + year +
'}';
}
}