一.Collection常见方法
1.在Java中,Collection接口代表的是什么集合?这种集合有什么特点? 2.在Collection集合中,又分了哪两种集合? 3.这两种集合的特点分别是什么? 4.Collection接口中的的常见方法有哪些(增删查)? 5.在add方法中,List系列与Set系列的返回值有什么不同? 6.remove方法中能使用下标删除吗? 7.contains方法中是使用的什么去比较对象的? 8.对于Set系列,能加入两个属性值相等的对象吗?
public class Demo221 {
public static void main(String[] args) {
System.out.println("1.Collection:单列集合,一次只添加一个数据");
System.out.println("2.单列集合里面又分为Set系列与List系列");
System.out.println("3.List系列的主要特点就是添加的元素是:有序可重复");
System.out.println("Set系列的主要特点就是添加的元素是:无序不可重复(类似于Python中的集合Set)");
System.out.println("4.Collection接口中的的常见方法:增add 删clear remove 查contains isEmpty size");
Collection<String> collection1 = new ArrayList<>();
System.out.println("5.对于list系列add方法一定返回true");
System.out.println(collection1.add("aaa"));
collection1.add("bbb");
collection1.add("ccc");
System.out.println(collection1);
System.out.println("对于Set系列,如果重复了就返回false");
Collection<String> collection2 = new HashSet<>();
System.out.println(collection2.add("aaa"));
System.out.println(collection2.add("aaa"));
System.out.println(collection2);
System.out.println("6.对于共性remove方法,Set无序,只能通过元素对象进行删除,方法有返回");
collection1.remove("aaa");
collection2.remove("a");
System.out.println("7.对于contains方法,右键方法goto选择implementation可以查看其在实现类中的实现");
System.out.println("底层判断是否相等使用的是equals方法判断,如果自定义对象,想要比较对象值相等,就重写equals吧");
Collection<Student> collection3 = new ArrayList<>();
Student s1 = new Student("爱丽丝", 16);
Student s2 = new Student("爱丽丝", 16);
collection3.add(s1);
System.out.println(s2 == s1);
System.out.println(collection3.contains(s2));
System.out.println("8.对于Set,只要对象地址不同,都可以加入");
Collection<Student> collection4 = new HashSet<>();
collection4.add(s1);
collection4.add(s2);
System.out.println(collection4);
System.out.println("返回是否为空与元素数量,最后删库跑路");
System.out.println(collection4.isEmpty() + " " + collection4.size());
collection4.clear();
}
}
class Student {
private String name;
private int age;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
//这里调用的是String的属性的对比
//如果是数组的话,就调用Arrays工具类去一个一个的比较数组内容,内容相等就返回对
return age == student.age && Objects.equals(name, student.name);
}
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 +
'}';
}
}
二.迭代器遍历Collection元素(可以在有元素要删除的时候用)
1.迭代器依赖索引吗?类名是什么? 2.如何获取迭代器的对象? 3.创建迭代器之后应该如何遍历? 4.如何在迭代器遍历的时候删除元素?
public class Demo222 {
public static void main(String[] args) {
System.out.println("1.迭代器不依赖索引,在Java中类是Iterator,是集合专用遍历方式");
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("aaa");
arrayList.add("bbb");
arrayList.add("ccc");
arrayList.add("ddd");
System.out.println("2.利用集合对象的方法,创建迭代器对象,默认指向0索引");
Iterator<String> iterator = arrayList.iterator();
System.out.println("3.判断当前位置是否有元素");
System.out.println("有元素则输出元素,然后后移,注意:遍历的时候不要用集合的方法增加或者删除元素");
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
System.out.println();
//再次获取新的迭代器
iterator = arrayList.iterator();
while (iterator.hasNext()) {
String str = iterator.next();
if (str.equals("ddd")) {
System.out.println("4.用迭代器的方法移除迭代器返回的最后一个元素");
iterator.remove();
}
}
System.out.println(arrayList);
}
}
三.增强for循环遍历与lambda表达式遍历
1.增强for遍历集合底层使用的是什么? 2.什么对象能够使用增强for遍历? 3.增强for循环格式? 4.如何使用lambda表达式 + Comsumer 接口遍历集合
public class Demo223 {
public static void main(String[] args) {
System.out.println("1.增强for遍历:底层就是迭代器");
System.out.println("2.所有的单列集合与数组才能用增强for遍历");
System.out.println("3.for(元素类型 元素名 :数组||单列集合名)");
int[] arr = {0, 1, 2, 3, 4, 5, 6, 7};
for (int i : arr) {
System.out.print(i + " ");
}
System.out.println();
Collection<String> clt = new ArrayList<>();
clt.add("爱丽丝");
clt.add("洛琪希");
for (String s : clt) {
System.out.print(s+" ");
}
System.out.println();
System.out.println("4.使用集合的forEach方法遍历集合");
clt.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.print(s+" ");
}
});
}
}
四.List常见方法:增删改查
List集合中,在remove Integer 类型的元素时,优先根据下标删除还是对象的值删除呢?
public class Demo224 {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("aaa");
System.out.println("1.根据下标增");
arrayList.add(1, "bbb");
System.out.println(arrayList);
System.out.println("2.根据下标删");
arrayList.remove(1);
System.out.println(arrayList);
System.out.println("3.根据下标修改,返回被修改的元素");
System.out.println(arrayList.set(0, "ccc"));
System.out.println("4.根据下标查");
System.out.println(arrayList.get(0));
System.out.println("5.List中默认优先根据下标删除元素");
System.out.println("当存储的是Integer数据类型时的特殊情况:想要删除特定数字,需要创建Integer对象");
ArrayList<Integer> arrayList2 = new ArrayList<>();
arrayList2.add(1);
arrayList2.add(2);
arrayList2.remove(Integer.valueOf(1));
System.out.println(arrayList2);
}
}
五.列表迭代器ListIterator:List第5种遍历方式
1.ListIterator与Iterator是什么关系?他有什么更多的用途? 2.ListIterator使用什么方法添加元素?添加元素的位置是怎么决定的?
public class Demo225 {
public static void main(String[] args) {
System.out.println("1.ListIterator继承于Iterator,是它的子接口,可以在遍历过程中加元素");
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add("aaa");
arrayList.add("bbb");
arrayList.add("ccc");
ListIterator<String> li = arrayList.listIterator();
System.out.println("2.add()增加元素,增加的位置在当前迭代器指向的位置,默认从0开始, 和remove不一样");
while (li.hasNext()){
li.add("嗨嗨嗨");
String str = li.next();
//尽量把不为空的写前面
if ("aaa".equals(str)){
li.remove();
li.add("eee");
}
}
System.out.println(arrayList);
}
}
六.ArrayList底层原理
1.ArrayList底层为数组 2.空参构造的集合,创建长度默认为0 3.添加第一个元素的时候,扩容为10 4.存满则自动扩容1.5倍(底层是原容量再加原容量右移一位之后的新容量) 5.果扩容之后也超过容量,则按照加入的元素量来扩容(有多少加多少 6.扩容使用arrays.copyOf,创建新的数组然后复制 看源码即可,顺着add方法往下走
public class Demo226 {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
System.out.println(arrayList);
}
}
七.LinkedList底层与LinkedList特有方法
LinkedList底层与LinkedList特有方法 LinkedList底层是双向链表: 1.源码中私有静态内部类是Node,包括item,prev,next 2.在List类中还有size,first,last代表规模和头尾节点 3.在new一个双向链表的时候,声明了size,first,last,全是空 void linkLast(E e) { final Node<E> l = last; final Node<E> newNode = new Node<>(l, e, null); last = newNode; if (l == null) first = newNode; else l.next = newNode; size++; modCount++; } 1.在addLast后,先设置一个l保存last 2.new了一个新节点new Node<>(l,e,null)(前一个元素,添加的元素,后一个元素) 3.把last定义为新增加的这个节点 4.如果last节点本来为空(也就是说这个双向链表才刚刚创建),那就把头节点first也设置为新增的元素 否则就设置l(前一个元素)的下一个节点为新增的元素 通过上面的代码我们可以看到,Java中LinkedList如果有至少一个节点 这个双向链表中的头节点和尾节点就都不是指向的空(根本就没有创建这种内部类的对象,只是起一个指向作用)
public class Demo227 {
public static void main(String[] args) {
LinkedList<Integer> linkedList = new LinkedList<>();
System.out.println("LinkedList独有的增删查方法");
linkedList.addFirst(1);
linkedList.addLast(2);
System.out.println(linkedList.getFirst());
System.out.println(linkedList.getLast());
linkedList.removeFirst();
linkedList.removeLast();
System.out.println(linkedList);
}
}
八.迭代器底层:以ArrayList为例
在ArrayList里面创建了一个私有的内部类的对象,这个对象,实现了迭代器这个接口 在接口对象里面:定义了一个下标,一个上一次返回的下标,还有一个是集合变化的次数的记录 hasNext():判断当前对象是否有元素,就是判断下标是否到达最大值。 next():在这里面注意,内部类使用外部类的元素使用的ArrayList.this.elementData,这里是为了区分外部类元素与内部类元素 每次next的时候都会看是否有集合的数量变化:如果有变化就会报错。
public class Demo228 {
public static void main(String[] args) {
//在代码中使用赋值语句,返回的是被赋值的那个数
int a = 0;
System.out.println((a++) + " " + (++a) + " " + (a = 1));
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("aaa");
arrayList.add("bbb");
arrayList.add("ccc");
//这里使用的是接口名接收的对象,故能够使用这个对象的方法
//但也只能给你用用实现的方法了,只要是接口,实现类的变量是都用不了的
Iterator<String> iterator = arrayList.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
}
}
九.外界调用私有内部类中的成员方法:两种方式
public class Demo229 {
public static void main(String[] args) {
Outer outer = new Outer();
Inter inter = outer.getInner1();
inter.show();
InnerFather innerFather = outer.getInner2();
innerFather.show();
//直接使用outer.getInner().show()是不行的
}
}
class Outer{
Inner1 getInner1(){
return new Inner1();
}
Inner2 getInner2(){
return new Inner2();
}
private class Inner1 implements Inter{
@Override
public void show() {
System.out.println("私有内部类的方法,外界可以使用接口接收并调用");
}
}
private class Inner2 extends InnerFather{
@Override
public void show() {
System.out.println("私有内部类的方法,外界可以使用父类接收并调用");
}
}
}
interface Inter{
void show();
}
abstract class InnerFather{
void show() {}
}