当前位置: 首页 > news >正文

0基础学java-day14

一、集合

前面我们保存多个数据使用的是数组,那么数组有不足的地方,我们分析一下

1.数组

2 集合 

  • 数据类型也可以不一样 

3.集合的框架体系 

  • Java 的集合类很多,主要分为两大类,如图 :[背下来]

 

package com.hspedu.collection_;import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;/*** @author 林然* @version 1.0*/
public class Collection_ {public static void main(String[] args) {//1. 集合主要是两组(单列集合 , 双列集合)//2. Collection 接口有两个重要的子接口 List 和Set , 他们的实现子类都是单列集合//3. Map 接口的实现子类 是双列集合,存放的 K-V//4. 把老师梳理的两张图记住ArrayList arrayList =new ArrayList();arrayList.add("jack");arrayList.add("tom");HashMap hashMap =new HashMap();hashMap.put("No1","北京");}
}

4.Collection 接口和常用方法

4.1Collection 接口实现类的特点

  • Collection 接口常用方法,以实现子类 ArrayList 来演示 

package com.hspedu.collection_;import java.util.ArrayList;
import java.util.List;/*** @author 林然* @version 1.0*/
public class CollectionMethod {@SuppressWarnings("all")public static void main(String[] args) {List list =new ArrayList();// add:添加单个元素list.add("jack");list.add(10);//这里相当于自动装箱了,添加的实际是对象list.add(true);System.out.println("list="+list);// remove:删除指定元素
//list.remove(0);//删除第一个元素list.remove(true);//指定删除某个元素System.out.println("list=" + list);// contains:查找元素是否存在System.out.println(list.contains("jack"));//T// size:获取元素个数System.out.println(list.size());//2// isEmpty:判断是否为空System.out.println(list.isEmpty());//F// clear:清空list.clear();System.out.println("list=" + list);// addAll:添加多个元素ArrayList list2=new ArrayList();list2.add("加油");list2.add("java大神");list.addAll(list2);System.out.println("list=" + list);// containsAll:查找多个元素是否都存在System.out.println(list.containsAll(list2));//T// removeAll:删除多个元素list.add("聊斋");list.removeAll(list2);System.out.println("list=" + list);//[聊斋]}
}

4.2 Collection 接口遍历元素方式 1-使用 Iterator(迭代器)

 

package com.hspedu.collection_;import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;/*** @author 林然* @version 1.0*/
@SuppressWarnings({"all"})
public class CollectionIterator {public static void main(String[] args) {Collection col = new ArrayList();col.add(new Book1("三国演义", "罗贯中", 10.1));col.add(new Book1("小李飞刀", "古龙", 5.1));col.add(new Book1("红楼梦", "曹雪芹", 34.6));//现在老师希望能够遍历 col 集合//1. 先得到 col 对应的 迭代器Iterator iterator =col.iterator();//2. 使用 while 循环遍历// while (iterator.hasNext()) {//判断是否还有数据// //返回下一个元素,类型是 Object// Object obj = iterator.next();// System.out.println("obj=" + obj);// }//教大家一个快捷键,快速生成 while => itit//显示所有的快捷键的的快捷键 ctrl + jwhile (iterator.hasNext()) {Object next =  iterator.next();System.out.println(next);}//3. 当退出 while 循环后 , 这时 iterator 迭代器,指向最后的元素// iterator.next();//NoSuchElementException//4. 如果希望再次遍历,需要重置我们的迭代器iterator = col.iterator();System.out.println("===第二次遍历===");while (iterator.hasNext()) {Object obj = iterator.next();System.out.println("obj=" + obj);}}
}
@SuppressWarnings({"all"})
class Book1 {private String name;private String author;private double price;public Book1(String name, String author, double price) {this.name = name;this.author = author;this.price = price;}@Overridepublic String toString() {return "Book1{" +"name='" + name + '\'' +", author='" + author + '\'' +", price=" + price +'}';}
}

4.3 Collection 接口遍历对象方式 2-for 循环增强

package com.hspedu.collection_;import java.util.ArrayList;
import java.util.Collection;/*** @author 林然* @version 1.0*/
public class CollectionFor {@SuppressWarnings("all")public static void main(String[] args) {Collection col = new ArrayList();col.add(new Book1("三国演义", "罗贯中", 10.1));col.add(new Book1("小李飞刀", "古龙", 5.1));col.add(new Book1("红楼梦", "曹雪芹", 34.6));//使用增强for循环for(Object k:col){System.out.println("book="+k);}}}

 4.4 课堂练习

package com.hspedu.collection_;import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;public class CollectionExercise {@SuppressWarnings({"all"})public static void main(String[] args) {List list = new ArrayList();list.add(new Dog("小黑", 3));list.add(new Dog("大黄", 100));list.add(new Dog("大壮", 8));//先使用for增强for (Object dog : list) {System.out.println("dog=" + dog);}//使用迭代器System.out.println("===使用迭代器来遍历===");Iterator iterator = list.iterator();while (iterator.hasNext()) {Object dog =  iterator.next();System.out.println("dog=" + dog);}}
}
/*** 创建  3个 Dog {name, age}  对象,放入到 ArrayList 中,赋给 List 引用* 用迭代器和增强for循环两种方式来遍历* 重写Dog 的toString方法, 输出name和age*/
class Dog {private String name;private int age;public Dog(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;}@Overridepublic String toString() {return "Dog{" +"name='" + name + '\'' +", age=" + age +'}';}
}

 二、List 

1.List 接口和常用方法 

1.1  List 接口基本介绍

package com.hspedu.list_;import java.util.ArrayList;
import java.util.List;/*** @author 林然* @version 1.0*/
public class List_ {@SuppressWarnings("all")public static void main(String[] args) {//1. List 集合类中元素有序(即添加顺序和取出顺序一致)、且可重复 [案例]List list = new ArrayList();list.add("jack");list.add("tom");list.add("mary");list.add("lsl");list.add("tom");System.out.println("list=" + list);
//2. List 集合中的每个元素都有其对应的顺序索引,即支持索引
// 索引是从 0 开始的System.out.println(list.get(3));//lsl
//3}
}

 1.2 List 接口的常用方法

package com.hspedu.list_;import java.util.ArrayList;
import java.util.List;/*** @author 林然* @version 1.0*/
public class ListMethod {@SuppressWarnings("all")public static void main(String[] args) {List list =new ArrayList();list.add("张三丰");list.add("贾宝玉");
// void add(int index, Object ele):在 index 位置插入 ele 元素//在 index = 1 的位置插入一个对象list.add(1, "林然");System.out.println("list=" + list);// boolean addAll(int index, Collection eles):从 index 位置开始将 eles 中的所有元素添加进来List list2 = new ArrayList();list2.add("jack");list2.add("tom");list.addAll(1, list2);System.out.println("list=" + list);// Object get(int index):获取指定 index 位置的元素// int indexOf(Object obj):返回 obj 在集合中首次出现的位置System.out.println(list.indexOf("tom"));//2// int lastIndexOf(Object obj):返回 obj 在当前集合中末次出现的位置list.add("林然");System.out.println("list=" + list);System.out.println(list.lastIndexOf("林然"));// Object remove(int index):移除指定 index 位置的元素,并返回此元素list.remove(0);System.out.println("list=" + list);// Object set(int index, Object ele):设置指定 index 位置的元素为 ele , 相当于是替换. list.set(1, "玛丽");System.out.println("list=" + list);// List subList(int fromIndex, int toIndex):返回从 fromIndex 到 toIndex 位置的子集合
// 注意返回的子集合 fromIndex <= subList < toIndexList returnlist = list.subList(0, 2);System.out.println("returnlist=" + returnlist);}
}

 1.3 List 接口课堂练习

package com.hspedu.list_;import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;public class ListExercise {@SuppressWarnings({"all"})public static void main(String[] args) {/*添加10个以上的元素(比如String "hello" ),在2号位插入一个元素"韩顺平教育",获得第5个元素,删除第6个元素,修改第7个元素,在使用迭代器遍历集合,要求:使用List的实现类ArrayList完成。*/List list = new ArrayList();for (int i = 0; i < 12; i++) {list.add("hello" + i);}System.out.println("list=" + list);//在2号位插入一个元素"韩顺平教育"list.add(1, "韩顺平教育");System.out.println("list=" + list);//获得第5个元素System.out.println("第五个元素=" + list.get(4));//删除第6个元素list.remove(5);System.out.println("list=" + list);//修改第7个元素list.set(6, "三国演义");System.out.println("list=" + list);//在使用迭代器遍历集合Iterator iterator = list.iterator();while (iterator.hasNext()) {Object obj =  iterator.next();System.out.println("obj=" + obj);}}
}

 1.4 List 的三种遍历方式 [ArrayList, LinkedList,Vector]

package com.hspedu.list_;import java.util.*;public class ListFor {@SuppressWarnings({"all"})public static void main(String[] args) {//List 接口的实现子类 Vector LinkedList//List list = new ArrayList();//List list = new Vector();List list = new LinkedList();list.add("jack");list.add("tom");list.add("鱼香肉丝");list.add("北京烤鸭子");//遍历//1. 迭代器Iterator iterator = list.iterator();while (iterator.hasNext()) {Object obj =  iterator.next();System.out.println(obj);}System.out.println("=====增强for=====");//2. 增强forfor (Object o : list) {System.out.println("o=" + o);}System.out.println("=====普通for====");//3. 使用普通forfor (int i = 0; i < list.size(); i++) {System.out.println("对象=" + list.get(i));}}
}

 1.5 实现类的课堂练习 2

package com.hspedu.list_;import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;@SuppressWarnings({"all"})
public class ListExercise02 {public static void main(String[] args) {//List list = new ArrayList();List list = new LinkedList();//List list = new Vector();list.add(new Book("红楼梦", "曹雪芹", 100));list.add(new Book("西游记", "吴承恩", 10));list.add(new Book("水浒传", "施耐庵", 19));list.add(new Book("三国", "罗贯中", 80));//list.add(new Book("西游记", "吴承恩", 10));//如何对集合进行排序//遍历for (Object o : list) {System.out.println(o);}//冒泡排序sort(list);System.out.println("==排序后==");for (Object o : list) {System.out.println(o);}}//静态方法//价格要求是从小到大public static void sort(List list) {int listSize = list.size();for (int i = 0; i < listSize - 1; i++) {for (int j = 0; j < listSize - 1 - i; j++) {//取出对象BookBook book1 = (Book) list.get(j);Book book2 = (Book) list.get(j + 1);if (book1.getPrice() > book2.getPrice()) {//交换list.set(j, book2);list.set(j + 1, book1);}}}}
}

package com.hspedu.list_;public class Book {private String name;private String author;private double price;public Book(String name, String author, double price) {this.name = name;this.author = author;this.price = price;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}@Overridepublic String toString() {return "名称:" + name + "\t\t价格:" + price + "\t\t作者:" + author;}
}

2.ArrayList 底层结构和源码分析

2.1 ArrayList 的注意事项

2.2 ArrayList 的底层操作机制源码分析(重点,难点.) 

 3.Vector 底层结构和源码剖析

3.1 Vector 的基本介绍

3.2 Vector ArrayList 的比较 

4.LinkedList 底层结构 

4.1 LinkedList 的全面说明

4.2 LinkedList 的底层操作机制 

【这里其实就是涉及数据结构的知识点】

package com.hspedu.list_;public class LinkedList01 {public static void main(String[] args) {//模拟一个简单的双向链表Node jack = new Node("jack");Node tom = new Node("tom");Node hsp = new Node("老韩");//连接三个结点,形成双向链表//jack -> tom -> hspjack.next = tom;tom.next = hsp;//hsp -> tom -> jackhsp.pre = tom;tom.pre = jack;Node first = jack;//让first引用指向jack,就是双向链表的头结点Node last = hsp; //让last引用指向hsp,就是双向链表的尾结点//演示,从头到尾进行遍历System.out.println("===从头到尾进行遍历===");while (true) {if(first == null) {break;}//输出first 信息System.out.println(first);first = first.next;}//演示,从尾到头的遍历System.out.println("====从尾到头的遍历====");while (true) {if(last == null) {break;}//输出last 信息System.out.println(last);last = last.pre;}//演示链表的添加对象/数据,是多么的方便//要求,是在 tom --------- 老韩直接,插入一个对象 smith//1. 先创建一个 Node 结点,name 就是 smithNode smith = new Node("smith");//下面就把 smith 加入到双向链表了smith.next = hsp;smith.pre = tom;hsp.pre = smith;tom.next = smith;//让first 再次指向jackfirst = jack;//让first引用指向jack,就是双向链表的头结点System.out.println("===从头到尾进行遍历===");while (true) {if(first == null) {break;}//输出first 信息System.out.println(first);first = first.next;}last = hsp; //让last 重新指向最后一个结点//演示,从尾到头的遍历System.out.println("====从尾到头的遍历====");while (true) {if(last == null) {break;}//输出last 信息System.out.println(last);last = last.pre;}}
}//定义一个Node 类,Node 对象 表示双向链表的一个结点
class Node {public Object item; //真正存放数据public Node next; //指向后一个结点public Node pre; //指向前一个结点public Node(Object name) {this.item = name;}public String toString() {return "Node name=" + item;}
}

 4.3 LinkedList 的增删改查案例

package com.hspedu.list_;import java.util.Iterator;
import java.util.LinkedList;/*** @author 韩顺平* @version 1.0*/
@SuppressWarnings({"all"})
public class LinkedListCRUD {public static void main(String[] args) {LinkedList linkedList = new LinkedList();linkedList.add(1);linkedList.add(2);linkedList.add(3);System.out.println("linkedList=" + linkedList);//演示一个删除结点的linkedList.remove(); // 这里默认删除的是第一个结点//linkedList.remove(2);System.out.println("linkedList=" + linkedList);//修改某个结点对象linkedList.set(1, 999);System.out.println("linkedList=" + linkedList);//得到某个结点对象//get(1) 是得到双向链表的第二个对象Object o = linkedList.get(1);System.out.println(o);//999//因为LinkedList 是 实现了List接口, 遍历方式System.out.println("===LinkeList遍历迭代器====");Iterator iterator = linkedList.iterator();while (iterator.hasNext()) {Object next =  iterator.next();System.out.println("next=" + next);}System.out.println("===LinkeList遍历增强for====");for (Object o1 : linkedList) {System.out.println("o1=" + o1);}System.out.println("===LinkeList遍历普通for====");for (int i = 0; i < linkedList.size(); i++) {System.out.println(linkedList.get(i));}//老韩源码阅读./* 1. LinkedList linkedList = new LinkedList();public LinkedList() {}2. 这时 linkeList 的属性 first = null  last = null3. 执行 添加public boolean add(E e) {linkLast(e);return true;}4.将新的结点,加入到双向链表的最后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;elsel.next = newNode;size++;modCount++;}*//*老韩读源码 linkedList.remove(); // 这里默认删除的是第一个结点1. 执行 removeFirstpublic E remove() {return removeFirst();}2. 执行public E removeFirst() {final Node<E> f = first;if (f == null)throw new NoSuchElementException();return unlinkFirst(f);}3. 执行 unlinkFirst, 将 f 指向的双向链表的第一个结点拿掉private E unlinkFirst(Node<E> f) {// assert f == first && f != null;final E element = f.item;final Node<E> next = f.next;f.item = null;f.next = null; // help GCfirst = next;if (next == null)last = null;elsenext.prev = null;size--;modCount++;return element;}*/}
}

4.4 ArrayList LinkedList 比较

三、Set 

1.Set 接口和常用方法 

1.1 Set 接口基本介绍

1.2 Set 接口的常用方法 

List 接口一样 , Set 接口也是 Collection 的子接口,因此,常用方法和 Collection 接口一样

1.3 Set 接口的遍历方式

1.4 Set 接口的常用方法举例 

package com.hspedu.set_;import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;@SuppressWarnings({"all"})
public class SetMethod {public static void main(String[] args) {//老韩解读//1. 以Set 接口的实现类 HashSet 来讲解Set 接口的方法//2. set 接口的实现类的对象(Set接口对象), 不能存放重复的元素, 可以添加一个null//3. set 接口对象存放数据是无序(即添加的顺序和取出的顺序不一致)//4. 注意:取出的顺序的顺序虽然不是添加的顺序,但是他的固定【就是每次得到的顺序的固定的】.Set set = new HashSet();set.add("john");set.add("lucy");set.add("john");//重复,由于重复,只会有一个set.add("jack");set.add("hsp");set.add("mary");set.add(null);//set.add(null);//再次添加null,由于重复,只会有一个for(int i = 0; i <10;i ++) {System.out.println("set=" + set);}//遍历//方式1: 使用迭代器System.out.println("=====使用迭代器====");Iterator iterator = set.iterator();while (iterator.hasNext()) {Object obj =  iterator.next();System.out.println("obj=" + obj);}set.remove(null);//方式2: 增强forSystem.out.println("=====增强for====");for (Object o : set) {System.out.println("o=" + o);}//set 接口对象,不能通过索引来获取}
}

2.HashSet

2.1 HashSet 的全面说明

package com.hspedu.set_;import java.util.HashSet;
import java.util.Set;@SuppressWarnings({"all"})
public class HashSet_ {public static void main(String[] args) {//老韩解读//1. 构造器走的源码/*public HashSet() {map = new HashMap<>();}2. HashSet 可以存放null ,但是只能有一个null,即元素不能重复*/Set hashSet = new HashSet();hashSet.add(null);hashSet.add(null);System.out.println("hashSet=" + hashSet);}
}

 2.2 HashSet 案例说明

package com.hspedu.set_;import java.util.HashSet;@SuppressWarnings({"all"})
public class HashSet01 {public static void main(String[] args) {HashSet set = new HashSet();//说明//1. 在执行add方法后,会返回一个boolean值//2. 如果添加成功,返回 true, 否则返回false//3. 可以通过 remove 指定删除哪个对象System.out.println(set.add("john"));//TSystem.out.println(set.add("lucy"));//TSystem.out.println(set.add("john"));//FSystem.out.println(set.add("jack"));//TSystem.out.println(set.add("Rose"));//Tset.remove("john");System.out.println("set=" + set);//3个//set  = new HashSet();System.out.println("set=" + set);//0//4 Hashset 不能添加相同的元素/数据?set.add("lucy");//添加成功set.add("lucy");//加入不了set.add(new Dog("tom"));//OKset.add(new Dog("tom"));//OkSystem.out.println("set=" + set);//在加深一下. 非常经典的面试题.//看源码,做分析, 先给小伙伴留一个坑,以后讲完源码,你就了然//去看他的源码,即 add 到底发生了什么?=> 底层机制.set.add(new String("hsp"));//okset.add(new String("hsp"));//加入不了.System.out.println("set=" + set);}
}
class Dog { //定义了Dog类private String name;public Dog(String name) {this.name = name;}@Overridepublic String toString() {return "Dog{" +"name='" + name + '\'' +'}';}
}

 2.3 HashSet 底层机制说明

package com.hspedu.set_;@SuppressWarnings({"all"})
public class HashSetStructure {public static void main(String[] args) {//模拟一个HashSet的底层 (HashMap 的底层结构)//1. 创建一个数组,数组的类型是 Node[]//2. 有些人,直接把 Node[] 数组称为 表Node[] table = new Node[16];//3. 创建结点Node john = new Node("john", null);table[2] = john;Node jack = new Node("jack", null);john.next = jack;// 将jack 结点挂载到johnNode rose = new Node("Rose", null);jack.next = rose;// 将rose 结点挂载到jackNode lucy = new Node("lucy", null);table[3] = lucy; // 把lucy 放到 table表的索引为3的位置.System.out.println("table=" + table);}
}
class Node { //结点, 存储数据, 可以指向下一个结点,从而形成链表Object item; //存放数据Node next; // 指向下一个结点public Node(Object item, Node next) {this.item = item;this.next = next;}
}

 【在这里我们可以看到他用得是equals,由于字符串改写了,其比较的是内容,之前的一个案例就在这里被解释了】

【如果table没到64,但是链表超过8,将会对table进行扩容】

 【下面的源码更加说明了上面的结论】

package com.hspedu.set_;import java.util.HashSet;/*** @author 韩顺平* @version 1.0*/
@SuppressWarnings({"all"})
public class HashSetSource {public static void main(String[] args) {HashSet hashSet = new HashSet();hashSet.add("java");//到此位置,第1次add分析完毕.hashSet.add("php");//到此位置,第2次add分析完毕hashSet.add("java");System.out.println("set=" + hashSet);/*对HashSet 的源码解读1. 执行 HashSet()public HashSet() {map = new HashMap<>();}2. 执行 add()public boolean add(E e) {//e = "java"return map.put(e, PRESENT)==null;//(static) PRESENT = new Object();}3.执行 put() , 该方法会执行 hash(key) 得到key对应的hash值 算法h = key.hashCode()) ^ (h >>> 16)public V put(K key, V value) {//key = "java" value = PRESENT 共享return putVal(hash(key), key, value, false, true);}4.执行 putValfinal V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {Node<K,V>[] tab; Node<K,V> p; int n, i; //定义了辅助变量//table 就是 HashMap 的一个数组,类型是 Node[]//if 语句表示如果当前table 是null, 或者 大小=0//就是第一次扩容,到16个空间.if ((tab = table) == null || (n = tab.length) == 0)n = (tab = resize()).length;//(1)根据key,得到hash 去计算该key应该存放到table表的哪个索引位置//并把这个位置的对象,赋给 p//(2)判断p 是否为null//(2.1) 如果p 为null, 表示还没有存放元素, 就创建一个Node (key="java",value=PRESENT)//(2.2) 就放在该位置 tab[i] = newNode(hash, key, value, null)if ((p = tab[i = (n - 1) & hash]) == null)tab[i] = newNode(hash, key, value, null);else {//一个开发技巧提示: 在需要局部变量(辅助变量)时候,在创建Node<K,V> e; K k; ////如果当前索引位置对应的链表的第一个元素和准备添加的key的hash值一样//并且满足 下面两个条件之一://(1) 准备加入的key 和 p 指向的Node 结点的 key 是同一个对象//(2)  p 指向的Node 结点的 key 的equals() 和准备加入的key比较后相同//就不能加入if (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))e = p;//再判断 p 是不是一颗红黑树,//如果是一颗红黑树,就调用 putTreeVal , 来进行添加else if (p instanceof TreeNode)e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);else {//如果table对应索引位置,已经是一个链表, 就使用for循环比较//(1) 依次和该链表的每一个元素比较后,都不相同, 则加入到该链表的最后//    注意在把元素添加到链表后,立即判断 该链表是否已经达到8个结点//    , 就调用 treeifyBin() 对当前这个链表进行树化(转成红黑树)//    注意,在转成红黑树时,要进行判断, 判断条件//    if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY(64))//            resize();//    如果上面条件成立,先table扩容.//    只有上面条件不成立时,才进行转成红黑树//(2) 依次和该链表的每一个元素比较过程中,如果有相同情况,就直接breakfor (int binCount = 0; ; ++binCount) {if ((e = p.next) == null) {p.next = newNode(hash, key, value, null);if (binCount >= TREEIFY_THRESHOLD(8) - 1) // -1 for 1sttreeifyBin(tab, hash);break;}if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))break;p = e;}}if (e != null) { // existing mapping for keyV oldValue = e.value;if (!onlyIfAbsent || oldValue == null)e.value = value;afterNodeAccess(e);return oldValue;}}++modCount;//size 就是我们每加入一个结点Node(k,v,h,next), size++if (++size > threshold)resize();//扩容afterNodeInsertion(evict);return null;}*/}
}

2.4 HashSet 课堂练习 1

package com.hspedu.set_;import java.util.HashSet;
import java.util.Objects;/*** @author 林然* @version 1.0*/
public class HashSetExercise {@SuppressWarnings("all")public static void main(String[] args) {/**定义一个 Employee 类,该类包含:private 成员属性 name,age 要求:创建 3 个 Employee 对象放入 HashSet 中当 name 和 age 的值相同时,认为是相同员工, 不能添加到 HashSet 集合中*/HashSet hashSet = new HashSet();hashSet.add(new Employee("milan", 18));//okhashSet.add(new Employee("smith", 28));//okhashSet.add(new Employee("milan", 18));//加入不成功System.out.println("hashSet=" + hashSet);}
}
//创建 Employee
class Employee{private String name;private int age;public Employee(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;}@Overridepublic String toString() {return "Employee{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Employee employee = (Employee) o;return age == employee.age &&Objects.equals(name, employee.name);}@Overridepublic int hashCode() {return Objects.hash(name, age);}
}

 2.5 HashSet 课后练习 2

3.LinkedHashSet 

3.1 LinkedHashSet 的全面说明

package com.hspedu.set_;import java.util.LinkedHashSet;
import java.util.Set;@SuppressWarnings({"all"})
public class LinkedHashSetSource {public static void main(String[] args) {//分析一下LinkedHashSet的底层机制Set set = new LinkedHashSet();set.add(new String("AA"));set.add(456);set.add(456);set.add(new Customer("刘", 1001));set.add(123);set.add("HSP");System.out.println("set=" + set);//1. LinkedHashSet 加入顺序和取出元素/数据的顺序一致//2. LinkedHashSet 底层维护的是一个LinkedHashMap(是HashMap的子类)//3. LinkedHashSet 底层结构 (数组table+双向链表)//4. 添加第一次时,直接将 数组table 扩容到 16 ,存放的结点类型是 LinkedHashMap$Entry//5. 数组是 HashMap$Node[] 存放的元素/数据是 LinkedHashMap$Entry类型/*//继承关系是在内部类完成.static class Entry<K,V> extends HashMap.Node<K,V> {Entry<K,V> before, after;Entry(int hash, K key, V value, Node<K,V> next) {super(hash, key, value, next);}}*/}
}
class Customer {private String name;private int no;public Customer(String name, int no) {this.name = name;this.no = no;}
}

3.2 LinkedHashSet 课后练习题

package com.hspedu.set_;import java.util.LinkedHashSet;
import java.util.Objects;@SuppressWarnings({"all"})
public class LinkedHashSetExercise {public static void main(String[] args) {LinkedHashSet linkedHashSet = new LinkedHashSet();linkedHashSet.add(new Car("奥拓", 1000));//OKlinkedHashSet.add(new Car("奥迪", 300000));//OKlinkedHashSet.add(new Car("法拉利", 10000000));//OKlinkedHashSet.add(new Car("奥迪", 300000));//加入不了linkedHashSet.add(new Car("保时捷", 70000000));//OKlinkedHashSet.add(new Car("奥迪", 300000));//加入不了System.out.println("linkedHashSet=" + linkedHashSet);}
}/*** Car 类(属性:name,price),  如果 name 和 price 一样,* 则认为是相同元素,就不能添加。 5min*/class Car {private String name;private double price;public Car(String name, double price) {this.name = name;this.price = price;}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}@Overridepublic String toString() {return "\nCar{" +"name='" + name + '\'' +", price=" + price +'}';}//重写equals 方法 和 hashCode//当 name 和 price 相同时, 就返回相同的 hashCode 值, equals返回t@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Car car = (Car) o;return Double.compare(car.price, price) == 0 &&Objects.equals(name, car.name);}@Overridepublic int hashCode() {return Objects.hash(name, price);}
}

 四、Map

1.Map 接口和常用方法 

1.1 Map 接口实现类的特点 [很实用]

package com.hspedu.map_;import java.util.HashMap;
import java.util.Map;/*** @author 林然* @version 1.0*/
public class Map_ {@SuppressWarnings("all")public static void main(String[] args) {//老韩解读 Map 接口实现类的特点, 使用实现类 HashMap//1. Map 与 Collection 并列存在。用于保存具有映射关系的数据:Key-Value(双列元素)//2. Map 中的 key 和 value 可以是任何引用类型的数据,会封装到 HashMap$Node 对象中//3. Map 中的 key 不允许重复,原因和 HashSet 一样,前面分析过源码. //4. Map 中的 value 可以重复//5. Map 的 key 可以为 null, value 也可以为 null ,注意 key 为 null,// 只能有一个,value 为 null ,可以多个//6. 常用 String 类作为 Map 的 key//7. key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到对应的 valueMap map =new HashMap();map.put("no1","林然");//k-vmap.put("no2","林然2");//k-vmap.put("no1","张三丰");//k-v 当有相同的 k , 就等价于替换.map.put("no3","张三丰");//k-vmap.put(null,null);//k-vmap.put(null,"abc");//k-v 当有相同的 k , 就等价于替换map.put("no4",null);//k-vmap.put(1, "赵敏");//k-vmap.put(new Object(), "金毛狮王");//k-v// 通过 get 方法,传入 key ,会返回对应的 valueSystem.out.println(map.get("no2"));//林然System.out.println(map);}
}

package com.hspedu.map_;import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;@SuppressWarnings({"all"})
public class MapSource_ {public static void main(String[] args) {Map map = new HashMap();map.put("no1", "韩顺平");//k-vmap.put("no2", "张无忌");//k-vmap.put(new Car(), new Person());//k-v//老韩解读//1. k-v 最后是 HashMap$Node node = newNode(hash, key, value, null)//2. k-v 为了方便程序员的遍历,还会 创建 EntrySet 集合 ,该集合存放的元素的类型 Entry, 而一个Entry//   对象就有k,v EntrySet<Entry<K,V>> 即: transient Set<Map.Entry<K,V>> entrySet;//3. entrySet 中, 定义的类型是 Map.Entry ,但是实际上存放的还是 HashMap$Node//   这时因为 static class Node<K,V> implements Map.Entry<K,V>//4. 当把 HashMap$Node 对象 存放到 entrySet 就方便我们的遍历, 因为 Map.Entry 提供了重要方法//   K getKey(); V getValue();Set set = map.entrySet();System.out.println(set.getClass());// HashMap$EntrySetfor (Object obj : set) {//System.out.println(obj.getClass()); //HashMap$Node//为了从 HashMap$Node 取出k-v//1. 先做一个向下转型Map.Entry entry = (Map.Entry) obj;System.out.println(entry.getKey() + "-" + entry.getValue() );}Set set1 = map.keySet();System.out.println(set1.getClass());Collection values = map.values();System.out.println(values.getClass());}
}class Car {}class Person{}

1.2 常用方法

 

package com.hspedu.map_;import java.util.HashMap;
import java.util.Map;/*** @author 林然* @version 1.0*/public class MapMethod {public static void main(String[] args) {//演示 map 接口常用方法Map map = new HashMap();map.put("邓超", new Book("", 100));//OKmap.put("邓超", "孙俪");//替换-> 一会分析源码map.put("王宝强", "马蓉");//OKmap.put("宋喆", "马蓉");//OKmap.put("刘令博", null);//OKmap.put(null, "刘亦菲");//OKmap.put("鹿晗", "关晓彤");//OKmap.put("hsp", "hsp 的老婆");System.out.println("map=" + map);
// remove:根据键删除映射关系map.remove(null);System.out.println("map=" + map);
// get:根据键获取值Object val = map.get("鹿晗");System.out.println("val=" + val);
// size:获取元素个数System.out.println("k-v=" + map.size());
// isEmpty:判断个数是否为 0System.out.println(map.isEmpty());//F
// clear:清除 k-v
//map.clear();System.out.println("map=" + map);
// containsKey:查找键是否存在System.out.println("结果=" + map.containsKey("hsp"));//T}
}class Book {private String name;private int num;public Book(String name, int num) {this.name = name;this.num = num;}
}

 1.3 Map 接口遍历方法

package com.hspedu.map_;import java.util.*;/*** @author 林然* @version 1.0*/
@SuppressWarnings("all")
public class MapFor {public static void main(String[] args) {Map map = new HashMap();map.put("邓超", "孙俪");map.put("王宝强", "马蓉");map.put("宋喆", "马蓉");map.put("刘令博", null);map.put(null, "刘亦菲");map.put("鹿晗", "关晓彤");//第一组: 先取出 所有的 Key , 通过 Key 取出对应的 ValueSet keyset = map.keySet();//(1) 增强 forSystem.out.println("-----第一种方式-------");for (Object key : keyset) {System.out.println(key + "-" + map.get(key));}//(2) 迭代器System.out.println("----第二种方式--------");Iterator iterator = keyset.iterator();while (iterator.hasNext()) {Object key = iterator.next();System.out.println(key + "-" + map.get(key));}//第二组: 把所有的 values 取出Collection values = map.values();//这里可以使用所有的 Collections 使用的遍历方法//(1) 增强 forSystem.out.println("---取出所有的 value 增强 for----");for (Object value : values) {System.out.println(value);}
//(2) 迭代器System.out.println("---取出所有的 value 迭代器----");Iterator iterator2 = values.iterator();while (iterator2.hasNext()){Object value = iterator2.next();System.out.println(value);}//第三组: 通过 EntrySet 来获取 k-vSet entrySet = map.entrySet();// EntrySet<Map.Entry<K,V>>
//(1) 增强 forSystem.out.println("----使用 EntrySet 的 for 增强(第 3 种)----");for (Object entry : entrySet) {
//将 entry 转成 Map.EntryMap.Entry m = (Map.Entry) entry;System.out.println(m.getKey() + "-" + m.getValue());}
//(2) 迭代器System.out.println("----使用 EntrySet 的 迭代器(第 4 种)----");Iterator iterator3 = entrySet.iterator();while (iterator3.hasNext()) {Object entry = iterator3.next();
//System.out.println(next.getClass());//HashMap$Node -实现-> Map.Entry (getKey,getValue)
//向下转型 Map.EntryMap.Entry m = (Map.Entry) entry;System.out.println(m.getKey() + "-" + m.getValue());}}
}

 1.4 Map 接口课堂练习

package com.hspedu.map_;import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;@SuppressWarnings({"all"})
public class MapExercise {public static void main(String[] args) {//完成代码Map hashMap = new HashMap();//添加对象hashMap.put(1, new Emp("jack", 300000, 1));hashMap.put(2, new Emp("tom", 21000, 2));hashMap.put(3, new Emp("milan", 12000, 3));//遍历2种方式//并遍历显示工资>18000的员工(遍历方式最少两种)//1. 使用keySet  -> 增强forSet keySet = hashMap.keySet();System.out.println("====第一种遍历方式====");for (Object key : keySet) {//先获取valueEmp emp = (Emp) hashMap.get(key);if(emp.getSal() >18000) {System.out.println(emp);}}//2. 使用EntrySet -> 迭代器//   体现比较难的知识点//   慢慢品,越品越有味道.Set entrySet = hashMap.entrySet();System.out.println("======迭代器======");Iterator iterator = entrySet.iterator();while (iterator.hasNext()) {Map.Entry entry =  (Map.Entry)iterator.next();//通过entry 取得key 和 valueEmp emp = (Emp) entry.getValue();if(emp.getSal() > 18000) {System.out.println(emp);}}}
}
/*** 使用HashMap添加3个员工对象,要求* 键:员工id* 值:员工对象** 并遍历显示工资>18000的员工(遍历方式最少两种)* 员工类:姓名、工资、员工id*/
class Emp {private String name;private double sal;private int id;public Emp(String name, double sal, int id) {this.name = name;this.sal = sal;this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getSal() {return sal;}public void setSal(double sal) {this.sal = sal;}public int getId() {return id;}public void setId(int id) {this.id = id;}@Overridepublic String toString() {return "Emp{" +"name='" + name + '\'' +", sal=" + sal +", id=" + id +'}';}
}

 2.Map 接口实现类-HashMap

2.1 HashMap 小结 

2.2 HashMap 底层机制及源码剖析 

package com.hspedu.map_;import java.util.HashMap;@SuppressWarnings({"all"})
public class HashMapSource1 {public static void main(String[] args) {HashMap map = new HashMap();map.put("java", 10);//okmap.put("php", 10);//okmap.put("java", 20);//替换valueSystem.out.println("map=" + map);///*老韩解读HashMap的源码+图解1. 执行构造器 new HashMap()初始化加载因子 loadfactor = 0.75HashMap$Node[] table = null2. 执行put 调用 hash方法,计算 key的 hash值 (h = key.hashCode()) ^ (h >>> 16)public V put(K key, V value) {//K = "java" value = 10return putVal(hash(key), key, value, false, true);}3. 执行 putValfinal V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {Node<K,V>[] tab; Node<K,V> p; int n, i;//辅助变量//如果底层的table 数组为null, 或者 length =0 , 就扩容到16if ((tab = table) == null || (n = tab.length) == 0)n = (tab = resize()).length;//取出hash值对应的table的索引位置的Node, 如果为null, 就直接把加入的k-v//, 创建成一个 Node ,加入该位置即可if ((p = tab[i = (n - 1) & hash]) == null)tab[i] = newNode(hash, key, value, null);else {Node<K,V> e; K k;//辅助变量// 如果table的索引位置的key的hash相同和新的key的hash值相同,// 并 满足(table现有的结点的key和准备添加的key是同一个对象  || equals返回真)// 就认为不能加入新的k-vif (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))e = p;else if (p instanceof TreeNode)//如果当前的table的已有的Node 是红黑树,就按照红黑树的方式处理e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);else {//如果找到的结点,后面是链表,就循环比较for (int binCount = 0; ; ++binCount) {//死循环if ((e = p.next) == null) {//如果整个链表,没有和他相同,就加到该链表的最后p.next = newNode(hash, key, value, null);//加入后,判断当前链表的个数,是否已经到8个,到8个,后//就调用 treeifyBin 方法进行红黑树的转换if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1sttreeifyBin(tab, hash);break;}if (e.hash == hash && //如果在循环比较过程中,发现有相同,就break,就只是替换value((k = e.key) == key || (key != null && key.equals(k))))break;p = e;}}if (e != null) { // existing mapping for keyV oldValue = e.value;if (!onlyIfAbsent || oldValue == null)e.value = value; //替换,key对应valueafterNodeAccess(e);return oldValue;}}++modCount;//每增加一个Node ,就size++if (++size > threshold[12-24-48])//如size > 临界值,就扩容resize();afterNodeInsertion(evict);return null;}5. 关于树化(转成红黑树)//如果table 为null ,或者大小还没有到 64,暂时不树化,而是进行扩容.//否则才会真正的树化 -> 剪枝final void treeifyBin(Node<K,V>[] tab, int hash) {int n, index; Node<K,V> e;if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)resize();}*/}
}

3.Map 接口实现类-Hashtable

3.1 HashTable 的基本介绍

 扩容【2倍+1】

package com.hspedu.map_;import java.util.Hashtable;@SuppressWarnings({"all"})
public class HashTableExercise {public static void main(String[] args) {Hashtable table = new Hashtable();//oktable.put("john", 100); //ok//table.put(null, 100); //异常 NullPointerException//table.put("john", null);//异常 NullPointerExceptiontable.put("lucy", 100);//oktable.put("lic", 100);//oktable.put("lic", 88);//替换table.put("hello1", 1);table.put("hello2", 1);table.put("hello3", 1);table.put("hello4", 1);table.put("hello5", 1);table.put("hello6", 1);System.out.println(table);//简单说明一下Hashtable的底层//1. 底层有数组 Hashtable$Entry[] 初始化大小为 11//2. 临界值 threshold 8 = 11 * 0.75//3. 扩容: 按照自己的扩容机制来进行即可.//4. 执行 方法 addEntry(hash, key, value, index); 添加K-V 封装到Entry//5. 当 if (count >= threshold) 满足时,就进行扩容//5. 按照 int newCapacity = (oldCapacity << 1) + 1; 的大小扩容.}
}

3.2 Hashtable HashMap 对比

4.Map 接口实现类-Properties 

4.1基本介绍

4.2 基本使用 

package com.hspedu.map_;import java.util.Properties;/*** @author Linran* @version 1.0*/
@SuppressWarnings({"all"})
public class Properties_ {public static void main(String[] args) {//老韩解读//1. Properties 继承  Hashtable//2. 可以通过 k-v 存放数据,当然key 和 value 不能为 null//增加Properties properties = new Properties();//properties.put(null, "abc");//抛出 空指针异常//properties.put("abc", null); //抛出 空指针异常properties.put("john", 100);//k-vproperties.put("lucy", 100);properties.put("lic", 100);properties.put("lic", 88);//如果有相同的key , value被替换System.out.println("properties=" + properties);//通过k 获取对应值System.out.println(properties.get("lic"));//88//删除properties.remove("lic");System.out.println("properties=" + properties);//修改properties.put("john", "约翰");System.out.println("properties=" + properties);}
}

 五、总结-开发中如何选择集合实现类(记住)

 5.1TreeSet源码解读

package com.hspedu.set_;import java.util.Comparator;
import java.util.TreeSet;/*** @author 林然* @version 1.0*/
@SuppressWarnings({"all"})
public class TreeSet_ {public static void main(String[] args) {//1. 当我们使用无参构造器,创建TreeSet时,仍然是无序的//2. 老师希望添加的元素,按照字符串大小来排序//3. 使用TreeSet 提供的一个构造器,可以传入一个比较器(匿名内部类)//   并指定排序规则//4. 简单看看源码/*1. 构造器把传入的比较器对象,赋给了 TreeSet的底层的 TreeMap的属性this.comparatorpublic TreeMap(Comparator<? super K> comparator) {this.comparator = comparator;}2. 在 调用 treeSet.add("tom"), 在底层会执行到if (cpr != null) {//cpr 就是我们的匿名内部类(对象)do {parent = t;//动态绑定到我们的匿名内部类(对象)comparecmp = cpr.compare(key, t.key);if (cmp < 0)t = t.left;else if (cmp > 0)t = t.right;else //如果相等,即返回0,这个Key就没有加入return t.setValue(value);} while (t != null);}*///        TreeSet treeSet = new TreeSet();TreeSet treeSet = new TreeSet(new Comparator() {@Overridepublic int compare(Object o1, Object o2) {//下面 调用String的 compareTo方法进行字符串大小比较//如果老韩要求加入的元素,按照长度大小排序//return ((String) o2).compareTo((String) o1);return ((String) o1).length() - ((String) o2).length();}});//添加数据.treeSet.add("jack");treeSet.add("tom");//3treeSet.add("sp");treeSet.add("a");treeSet.add("abc");//3,并不会加入System.out.println("treeSet=" + treeSet);}
}

 5.2 TreeMap源码解读

package com.hspedu.map_;import java.util.Comparator;
import java.util.TreeMap;/*** @author 林然* @version 1.0*/
@SuppressWarnings({"all"})
public class TreeMap_ {public static void main(String[] args) {//使用默认的构造器,创建TreeMap, 是无序的(也没有排序)/*老韩要求:按照传入的 k(String) 的大小进行排序*/
//        TreeMap treeMap = new TreeMap();TreeMap treeMap = new TreeMap(new Comparator() {@Overridepublic int compare(Object o1, Object o2) {//按照传入的 k(String) 的大小进行排序//按照K(String) 的长度大小排序//return ((String) o2).compareTo((String) o1);return ((String) o2).length() - ((String) o1).length();}});treeMap.put("jack", "杰克");treeMap.put("tom", "汤姆");treeMap.put("kristina", "克瑞斯提诺");treeMap.put("smith", "斯密斯");treeMap.put("hsp", "韩顺平");//加入不了,会把汤姆修改成韩顺平System.out.println("treemap=" + treeMap);/*老韩解读源码:1. 构造器. 把传入的实现了 Comparator接口的匿名内部类(对象),传给给TreeMap的comparatorpublic TreeMap(Comparator<? super K> comparator) {this.comparator = comparator;}2. 调用put方法2.1 第一次添加, 把k-v 封装到 Entry对象,放入rootEntry<K,V> t = root;if (t == null) {compare(key, key); // type (and possibly null) checkroot = new Entry<>(key, value, null);size = 1;modCount++;return null;}2.2 以后添加Comparator<? super K> cpr = comparator;if (cpr != null) {do { //遍历所有的key , 给当前key找到适当位置parent = t;cmp = cpr.compare(key, t.key);//动态绑定到我们的匿名内部类的compareif (cmp < 0)t = t.left;else if (cmp > 0)t = t.right;else  //如果遍历过程中,发现准备添加Key 和当前已有的Key 相等,就不添加return t.setValue(value);} while (t != null);}*/}
}

 六、Collections 工具类

1 Collections 工具类介绍 

2 排序操作:(均为 static 方法) 

package com.hspedu.collections_;import java.util.*;/*** @author 林然* @version 1.0*/
@SuppressWarnings("all")
public class Collections_ {public static void main(String[] args) {//创建 ArrayList 集合,用于测试.List list = new ArrayList();list.add("tom");list.add("smith");list.add("king");list.add("milan");list.add("tom");// reverse(List):反转 List 中元素的顺序Collections.reverse(list);System.out.println(list);// shuffle(List):对 List 集合元素进行随机排序// for (int i = 0; i < 5; i++) {// Collections.shuffle(list);// System.out.println("list=" + list);//sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序Collections.sort(list);System.out.println("自然排序后");System.out.println("list=" + list);//按照首字母进行排序// sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
//我们希望按照 字符串的长度大小排序Collections.sort(list, new Comparator() {@Overridepublic int compare(Object o1, Object o2) {
//可以加入校验代码.return ((String) o2).length() - ((String) o1).length();}});System.out.println("字符串长度大小排序=" + list);// swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换
//比如Collections.swap(list, 0, 1);System.out.println("交换后的情况");System.out.println("list=" + list);//Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素System.out.println("自然顺序最大元素=" + Collections.max(list));//Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素
//比如,我们要返回长度最大的元素Object maxObject = Collections.max(list, new Comparator() {@Overridepublic int compare(Object o1, Object o2) {return ((String)o1).length() - ((String)o2).length();}});System.out.println("长度最大的元素=" + maxObject);//Object min(Collection)//Object min(Collection,Comparator)//上面的两个方法,参考 max 即可//int frequency(Collection,Object):返回指定集合中指定元素的出现次数System.out.println("tom 出现的次数=" + Collections.frequency(list, "tom"));//void copy(List dest,List src):将 src 中的内容复制到 dest 中ArrayList dest = new ArrayList();
//为了完成一个完整拷贝,我们需要先给 dest 赋值,大小和 list.size()一样for(int i = 0; i < list.size(); i++) {dest.add("");}
//拷贝Collections.copy(dest, list);System.out.println("dest=" + dest);//boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值
//如果 list 中,有 tom 就替换成 汤姆Collections.replaceAll(list, "tom", "汤姆");System.out.println("list 替换后=" + list);}
}

七、本章作业

1.作业一 

package com.hspedu.homework;import java.util.ArrayList;
import java.util.Collections;/*** @author 林然* @version 1.0*/
@SuppressWarnings("all")
public class homework1 {public static void main(String[] args) {News1 new1=new News1("新冠确诊病例超千万,数百万印度教信徒赴恒河\"圣浴\"引民众担忧");News1 new2=new News1("男子突然想起2个月前钓的鱼还在网兜里,捞起一看赶紧放生");ArrayList arrayList =new ArrayList();arrayList.add(new1);arrayList.add(new2);Collections.reverse(arrayList);for (Object k:arrayList) {News1 k1 = (News1)k;if(k1.getTitle().length()>=15)System.out.println(k1.getTitle().substring(0, 15) + "...");elseSystem.out.println(k1.getTitle());}}
}
class News1{private String title;private String content;public News1(String title) {this.title = title;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}@Overridepublic String toString() {return "News{" +"title='" + title + '\'' +", content='" + content + '\'' +'}';}
}

 2.作业二

package com.hspedu.homework;import java.util.ArrayList;
import java.util.Iterator;@SuppressWarnings({"all"})
public class Homework02 {public static void main(String[] args) {ArrayList arrayList = new ArrayList();Car car = new Car("宝马", 400000);Car car2 = new Car("宾利",5000000);//1.add:添加单个元素arrayList.add(car);arrayList.add(car2);System.out.println(arrayList);//* 2.remove:删除指定元素arrayList.remove(car);System.out.println(arrayList);//* 3.contains:查找元素是否存在System.out.println(arrayList.contains(car));//F//* 4.size:获取元素个数System.out.println(arrayList.size());//1//* 5.isEmpty:判断是否为空System.out.println(arrayList.isEmpty());//F//* 6.clear:清空//System.out.println(arrayList.clear(););//* 7.addAll:添加多个元素System.out.println(arrayList);arrayList.addAll(arrayList);//2个宾利System.out.println(arrayList);//* 8.containsAll:查找多个元素是否都存在arrayList.containsAll(arrayList);//T//* 9.removeAll:删除多个元素//arrayList.removeAll(arrayList); //相当于清空//* 使用增强for和 迭代器来遍历所有的car , 需要重写 Car 的toString方法for (Object o : arrayList) {System.out.println(o);//}System.out.println("===迭代器===");Iterator iterator = arrayList.iterator();while (iterator.hasNext()) {Object next =  iterator.next();System.out.println(next);}}
}
/*** 使用ArrayList 完成对 对象 Car {name, price} 的各种操作* 1.add:添加单个元素* 2.remove:删除指定元素* 3.contains:查找元素是否存在* 4.size:获取元素个数* 5.isEmpty:判断是否为空* 6.clear:清空* 7.addAll:添加多个元素* 8.containsAll:查找多个元素是否都存在* 9.removeAll:删除多个元素* 使用增强for和 迭代器来遍历所有的car , 需要重写 Car 的toString方法*/
class Car {private String name;private double price;public Car(String name, double price) {this.name = name;this.price = price;}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}@Overridepublic String toString() {return "Car{" +"name='" + name + '\'' +", price=" + price +'}';}
}

 3.作业三

package com.hspedu.homework;import java.util.*;/*** @author 林然* @version 1.0*/
public class homework3 {@SuppressWarnings("all")public static void main(String[] args) {Map m = new HashMap();m.put("jack",650);m.put("tom",1200);m.put("smith",2900);m.replace("jack",2600);Set keys =m.keySet();//更新工资for(Object k :keys){   int salary=(int)(m.get(k));m.replace(k,salary+100);}//遍历集合中的员工//遍历 EntrySetSet entrySet = m.entrySet();//迭代器Iterator iterator = entrySet.iterator();while (iterator.hasNext()) {Map.Entry entry =  (Map.Entry)iterator.next();System.out.println(entry.getKey() + "-" + entry.getValue());}System.out.println("====遍历所有的工资====");Collection values = m.values();for (Object value : values) {System.out.println("工资=" + value);}}
}

 4.作业四

5.作业五 

//package com.hspedu.homework;
//
//import java.util.TreeSet;
////@SuppressWarnings({"all"})
//public class Homework05 {
//    public static void main(String[] args) {
//        TreeSet treeSet = new TreeSet();
//        //分析源码
//        //add 方法,因为 TreeSet() 构造器没有传入Comparator接口的匿名内部类
//        //所以在底层 Comparable<? super K> k = (Comparable<? super K>) key;
//        //即 把 Perosn转成 Comparable类型
//        treeSet.add(new Person());//ClassCastException.
//        treeSet.add(new Person());//ClassCastException.
//        treeSet.add(new Person());//ClassCastException.
//        treeSet.add(new Person());//ClassCastException.
//        treeSet.add(new Person());//ClassCastException.
//
//        System.out.println(treeSet);
//
//    }
//}
//
//class Person implements Comparable{
//
//    @Override
//    public int compareTo(Object o) {
//        return 0;
//    }
//}

 6.作业六

【只要id和name不一样,那么我们认为他们不是同一个对象】

【remove中是利用1001和CC来计算哈希值,也就是他没办法找到p1所在的位置【1001+AA】】

package com.hspedu.homework;import java.util.HashSet;
import java.util.Objects;@SuppressWarnings({"all"})
public class Homework06 {public static void main(String[] args) {HashSet set = new HashSet();//okPerson p1 = new Person(1001,"AA");//okPerson p2 = new Person(1002,"BB");//okset.add(p1);//okset.add(p2);//okp1.name = "CC";set.remove(p1);System.out.println(set);//2set.add(new Person(1001,"CC"));System.out.println(set);//3set.add(new Person(1001,"AA"));System.out.println(set);//4}
}class Person {public String name;public int id;public Person(int id, String name) {this.name = name;this.id = id;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Person person = (Person) o;return id == person.id &&Objects.equals(name, person.name);}@Overridepublic int hashCode() {return Objects.hash(name, id);}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", id=" + id +'}';}
}

7.作业七

相关文章:

0基础学java-day14

一、集合 前面我们保存多个数据使用的是数组&#xff0c;那么数组有不足的地方&#xff0c;我们分析一下 1.数组 2 集合 数据类型也可以不一样 3.集合的框架体系 Java 的集合类很多&#xff0c;主要分为两大类&#xff0c;如图 &#xff1a;[背下来] package com.hspedu.c…...

创建conan包-工具链

创建conan包-工具链 1 Toolchains 本文是基于对conan官方文档Toolchains翻译而来&#xff0c; 更详细的信息可以去查阅conan官方文档。 1 Toolchains Toolchains are the new way to integrate with build systems in Conan. Recipes can define a generate() method that wi…...

IntelliJ IDE 插件开发 | (二)UI 界面与数据持久化

系列文章 IntelliJ IDE 插件开发 |&#xff08;一&#xff09;快速入门 前言 在上一篇文章中介绍了在IDEA下开发、运行和安装插件的基本步骤&#xff0c;因此创建项目等基础步骤不再赘述&#xff0c;本文则开始介绍如何进行 UI 界面的开发以及相关数据的持久化存储&#xff…...

使用vue UI安装路由插件

1.使用vue创建项目 vue create vue-appvue ui 2.使用vue ui界面创建管理项目 终端页面输入&#xff1a;vue ui 创建项目 安装完成。可以直接在ui界面运行&#xff0c;也可以在编辑器中使用命令运行 安装路由&#xff0c;安装状态 选择插件 - 添加vue-router、添加vuex 安装…...

RPG项目01_脚本代码

基于“RPG项目01_场景及人物动画管理器”&#xff0c;我们创建一个XML文档 在资源文件夹下创建一个文件夹&#xff0c; 命名为Xml 将Xnl文档拖拽至文件夹中&#xff0c; 再在文件夹的Manager下新建脚本LoadManager 写代码&#xff1a; using System.Collections; using System…...

目标检测YOLO实战应用案例100讲-交通目标数据集构建及高性能检测算法研究与应用

目录 前言 国内外研究现状 目标检测研究现状 目标检测数据集研究现状...

浅谈Vue.js的计算属性computed

什么是computed属性 computed 属性用于声明计算属性&#xff0c;这些属性的值是基于其他响应式属性计算而来的&#xff0c;当依赖的响应式属性发生变化时&#xff0c;计算属性会自动重新计算。 与Vue.js 2相比&#xff0c;Vue.js 3的 computed 属性语法稍有变化&#xff0c;不…...

Linux常用指令详解

目录 前言&#xff1a; Linux的目录结构 Linux常用指令简介 whoami指令 ls指令 pwd指令 cd指令 tree指令 touch指令 mkdir指令 rmdir指令与rm指令 man指令 cp&#xff08;copy&#xff09;指令 mv&#xff08;move&#xff09;指令 cat指令 重定向及重定向的类型…...

Nginx(性能优化)

到这里文章的篇幅较长了&#xff0c;最后再来聊一下关于Nginx的性能优化&#xff0c;主要就简单说说收益最高的几个优化项&#xff0c;在这块就不再展开叙述了&#xff0c;毕竟影响性能都有多方面原因导致的&#xff0c;比如网络、服务器硬件、操作系统、后端服务、程序自身、数…...

机器学习笔记 - 如何在Python中对网格和点云进行体素化?

一、简述 本文主要是为了了解如何生成体素表示,体素之于3D就像像素之于2D。体素本质上是 3D 像素,但它们不是正方形,而是完美的立方体。 理论上,体素是复制现实的完美建模技术。 这里我们要了解四个广泛流行的 Python 库(Open3D、Trimesh、PyVista、pyntcloud )生成点云…...

冒个泡!OceanBase亮相 2023 新加坡金融科技节

近日&#xff0c;OceanBase 亮相 Singapore Fintech Festival 2023&#xff08;2023 新加坡金融科技节&#xff09;&#xff01;本届新加坡金融科技节于 2023 年 11 月 15 日至 17 日在新加坡博览展览中心举行&#xff0c;展会期间&#xff0c;OceanBase 得到了众多金融科技机构…...

正则表达式(5):常用符号

正则表达式&#xff08;5&#xff09;&#xff1a;常用符号 小结 本博文转载自 在本博客中&#xff0c;”正则表达式”为一系列文章&#xff0c;如果你想要从头学习怎样在Linux中使用正则&#xff0c;可以参考此系列文章&#xff0c;直达链接如下&#xff1a; 在Linux中使用正…...

Web安全漏洞分析-XSS(下)

随着互联网的迅猛发展&#xff0c;Web应用的普及程度也愈发广泛。然而&#xff0c;随之而来的是各种安全威胁的不断涌现&#xff0c;其中最为常见而危险的之一就是跨站脚本攻击&#xff08;Cross-Site Scripting&#xff0c;简称XSS&#xff09;。XSS攻击一直以来都是Web安全领…...

金南瓜SECS/GEM C# SDK 快速使用指南

本文对如何使用金南瓜SECS/GEM C# SDK 快速创建一个满足SECS/GEM通信要求的应用程序&#xff0c;只需简单3步完成。 第一步&#xff1a;创建C# .NET程序 示例使用Visual Studio 2010&#xff0c;使用者可以选择更高级版本 Visual Studio 第二步&#xff1a;添加DLL库引用&am…...

在一个没有超级用户的mongodb 生产库上如何添加超级用户

说来这个问题&#xff0c;都觉得不可思议&#xff0c;一个数据库怎么没有超级用户呢&#xff0c;我们知道&#xff0c;MYSQL&#xff0c;PG&#xff0c;ORACLE等&#xff0c;创建好后&#xff0c;都有一个默认的超级用户&#xff0c;MONGODB也有超级用户&#xff0c;但需要自己…...

排序算法之二:冒泡排序

冒泡排序的思路 冒泡排序是交换排序 基本思想&#xff1a;所谓交换&#xff0c;就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置&#xff0c;交换排序的特点是&#xff1a;将键值较大的记录向序列的尾部移动&#xff0c;键值较小的记录向序列的前部移动…...

一键搭建你的hnust请假条

hnust请假条 湖南科技大学请假条生成器 https://hnust.rick.icu/new &#xff08;直接使用&#xff09; Hnust Leave Note 去github https://github.com/rickhqh/hnust_leave_note 效果展示 界面展示效果图 v2.0 更新 vant和vue重构了整个源码同步学校新版请假条样式修复了…...

C练习题13

单项选择题(本大题共20小题,每小题2分,共40分。在每小题给出的四个备选项中,选出一个正确的答案,并将所选项前的字母填写在答题纸的相应位置上。) 1.结构化程序由三种基本结构组成、三种基本结构组成的算法是() A.可以完成任何复杂的任务 B. 只能完成部分复杂的任务 C. 只能完…...

交易历史记录20231206 记录

昨日回顾&#xff1a; select top 10000 * from dbo.CODEINFO A left join dbo.全部&#xff21;股20231206010101 B ON A.CODE B.代码 left join dbo.全部&#xff21;股20231206CONF D on A.CODED.代码left join dbo.全部&#xff21;股20231206 G on A.CODEG.代码 left…...

1-5总体分布的推断

...

深信服技术认证“SCSA-S”划重点:XSS漏洞

为帮助大家更加系统化地学习网络安全知识&#xff0c;以及更高效地通过深信服安全服务认证工程师考核&#xff0c;深信服特别推出“SCSA-S认证备考秘笈”共十期内容&#xff0c;“考试重点”内容框架&#xff0c;帮助大家快速get重点知识~ 划重点来啦 *点击图片放大展示 深信服…...

MIT6S081-Lab2总结

大家好&#xff0c;我叫徐锦桐&#xff0c;个人博客地址为www.xujintong.com&#xff0c;github地址为https://github.com/xjintong。平时记录一下学习计算机过程中获取的知识&#xff0c;还有日常折腾的经验&#xff0c;欢迎大家访问。 Lab2就是了解一下xv6的系统调用流程&…...

CMMI5大成熟度等级和4大过程域

CMMI&#xff08;Capability Maturity Model Integration&#xff0c;能力成熟度模型集成&#xff09;模型系列是帮助组织改进其过程的最佳实践的集合。这些模型由来自产业界、政府以及软件工程研究所&#xff08;Software Engineering Institute&#xff0c; SEI&#xff09;的…...

c++新经典模板与泛型编程:const修饰符的移除与增加

const修饰符的移除 让你来写移除const修饰符&#xff0c;你会怎么样来写&#xff1f; &#x1f602;&#x1f602;trait类模板&#xff0c;如下 #include <iostream>// 泛化版本 template<typename T> struct RemoveConst {using type T; };// 特化版本 template…...

AUTOSAR汽车电子嵌入式编程精讲300篇-基于加密算法的车载CAN总线安全通信

目录 前言 研究现状 系统架构研究 异常检测研究 认证与加密研究 相关技术 2.1车联网 2.2车载网络及总线 2.2.1 CAN总线基础 2.2.2 CAN总线网络安全漏洞 2.2.3 CAN总线信息安全需求 2.3密码算法 2.3.1 AES算法 2.3.2 XTEA算法 CAN网络建模与仿真 3.1 CAN网络建模…...

4-Docker命令之docker start

1.docker start介绍 docker start命令是用来启动一个或多个已经被停止的docker容器。 2.docker start用法 docker start [参数] container [container......] [root@centos79 ~]# docker start --helpUsage: docker start [OPTIONS] CONTAINER [CONTAINER...]Start one or…...

AWS Remote Control ( Wi-Fi ) on i.MX RT1060 EVK - 2 “架构 AWS”

接续上一章节&#xff0c;我们把开发环境架设好之后&#xff0c;此章节叙述如何建立 AWS IoT 环境&#xff0c;请务必已经有 AWS Account&#xff0c;申请 AWS Account 之流程将不在此说明。 III-1. 登入AWS IoT&#xff0c; 在“管理”>“所有装置”>“实物”下点击“建…...

日志框架梳理(Log4j,Reload4j,JUL,JCL,SLF4J,Logback,Log4j2)

原文链接 日志框架发展历程 在了解日志框架时总会列出一系列框架&#xff1a;Log4j&#xff0c;Reload4j&#xff0c;JUL&#xff0c;JCL&#xff0c;SLF4J&#xff0c;Logback&#xff0c;Log4j2&#xff0c;这么多框架让人感到混乱&#xff0c;该怎么选取、该怎么用。接下来…...

内核无锁队列kfifo

文章目录 1、抛砖引玉2、内核无锁队列kfifo2.1 kfifo结构2.2 kfifo分配内存2.3 kfifo初始化2.4 kfifo释放2.5 kfifo入队列2.6 kfifo出队列2.7 kfifo的判空和判满2.8 关于内存屏障 1、抛砖引玉 昨天遇到这样一个问题&#xff0c;有多个生产者&#xff0c;多个消费者&#xff0c…...

18、XSS——cookie安全

文章目录 1、cookie重要字段2、子域cookie机制3、路径cookie机制4、HttpOnly Cookie机制5、Secure Cookie机制6、本地cookie与内存cookie7、本地存储方式 一般来说&#xff0c;同域内浏览器中发出的任何一个请求都会带上cookie&#xff0c;无论请求什么资源&#xff0c;请求时&…...

从零开发短视频电商 Jmeter压测示例模板详解(无认证场景)

文章目录 添加线程组添加定时器添加HTTP请求默认值添加HTTP头管理添加HTTP请求添加结果断言响应断言 Response AssertionJSON断言 JSON Assertion持续时间断言 Duration Assertion 添加察看结果树添加聚合报告添加表格察看结果参考 以压测百度搜索为例 https://www.baidu.com/s…...

C++可以函数重载而C不可以的原因

函数重载是指在同一个作用域内&#xff0c;可以定义多个函数&#xff0c;它们具有相同的名称但是参数列表不同。函数重载的主要原理是函数的签名不同&#xff0c;而在 C 中&#xff0c;函数签名包括函数的名称和参数列表。而在 C 中&#xff0c;函数的标识仅依赖于函数的名称&a…...

Spark常见算子汇总

创建RDD 在Spark中创建RDD的方式分为三种: 从外部存储创建RDD从集合中创建RDD从其他RDD创建 textfile 调用SparkContext.textFile()方法&#xff0c;从外部存储中读取数据来创建 RDD parallelize 调用SparkContext 的 parallelize()方法&#xff0c;将一个存在的集合&…...

【华为数据之道学习笔记】3-1 基于数据特性的分类管理框架

华为根据数据特性及治理方法的不同对数据进行了分类定义&#xff1a;内部数据和外部数据、结构化数据和非结构化数据、元数据。其中&#xff0c;结构化数据又进一步划分为基础数据、主数据、事务数据、报告数据、观测数据和规则数据。 对上述数据分类的定义及特征描述。 分类维…...

电脑版便签软件怎么设置在桌面上显示?

对于不少上班族来说&#xff0c;如果想要在使用电脑办公的时候&#xff0c;随手记录一些常用的工作资料、工作注意事项等内容&#xff0c;直接在电脑上使用便签软件记录是比较方便的。电脑桌面便签工具不仅方便我们随时记录各类工作事项&#xff0c;而且支持我们快速便捷使用这…...

【华为数据之道学习笔记】2-建立企业级数据综合治理体系

数据作为一种新的生产要素&#xff0c;在企业构筑竞争优势的过程中起着重要作用&#xff0c;企业应将数据作为一种战略资产进行管理。数据从业务中产生&#xff0c;在IT系统中承载&#xff0c;要对数据进行有效治理&#xff0c;需要业务充分参与&#xff0c;IT系统确保遵从&…...

【IC前端虚拟项目】git和svn项目托管平台的简单使用说明

【IC前端虚拟项目】数据搬运指令处理模块前端实现虚拟项目说明-CSDN博客 代码托管在gitee平台上&#xff0c;进去后会看到文档目录“MVU芯片前端设计验证虚拟项目”和工程目录“mvu_prj”&#xff0c;可以通过git来下载工程&#xff1a; git clone gitgitee.com:gjm9999/ic_vi…...

C++ IO库

IO类 IO对象不能拷贝和赋值 iostream 表示形式的变化&#xff1a; 将100转换成二进制序列 然后格式化输出 x,y共用一块内存 输出的时候用不同的方式解析同一块内存 操作 格式化&#xff1a;内部表示转换为相应字节序列 缓存&#xff1a;要输出的内容放到缓存 编码转换&…...

Springboot 项目关于版本升级到 3.x ,JDK升级到17的相关问题

由于spring 停止对2.x 版本的维护&#xff0c;以及 jdk 频繁发布等客观因素&#xff0c;现需要对已有springboot 工程做一次全面升级&#xff1b;已因对市面上第三方等依赖库的兼容问题&#xff1b; 现有工程使用哥技术栈是版本&#xff1a; freemarker &#xff1a;2.3.32 spr…...

QGraphicsView实现简易地图7『异步加载-多瓦片-无底图』

前文链接&#xff1a;QGraphicsView实现简易地图6『异步加载-单瓦片-无底图』 前一篇文章提到的异步单瓦片加载&#xff0c;是指线程每准备好一个瓦片数据后&#xff0c;立刻抛出信号让主线程加载。而本篇异步多瓦片加载是指线程准备好所有瓦片数据后&#xff0c;一起抛出信号让…...

Spring Boot学习(三十三):集成kafka

前言 下面是zookeeper和kafka的官网下载地址&#xff0c;大家可以学习下载 zookeeper下载地址&#xff1a;http://zookeeper.apache.org/releases.html kafka下载地址&#xff1a;http://kafka.apache.org/downloads.html 1、添加依赖 在 pom.xml 文件中添加kafka依赖&am…...

MOSFET

MOSFET 电子元器件百科 文章目录 MOSFET前言一、MOSFET是什么二、MOSFET类别三、MOSFET应用实例四、MOSFET作用原理总结前言 MOSFET是一种常见的半导体器件,通过栅极电场控制通道区的导通特性,以控制电流流动。它在现代电子电路中发挥着重要的作用,并广泛应用于各种应用领域…...

DriveWorks——参数化设计非标定制利器

DriveWorks基本介绍 DriveWorks是一套被 SOLIDWORKS 认可为金牌合作伙伴产品的设计自动化软件。DriveWorks 可自动创建特定于订单的销售文档和 SOLIDWORKS 制造数据。减少重复性任务&#xff0c;消除错误&#xff0c;增加销售额&#xff0c;并在创纪录的时间内交付定制产品。 为…...

DevEco Studio集成ArkUI-X

语雀知识库地址&#xff1a;语雀HarmonyOS知识库 飞书知识库地址&#xff1a;飞书HarmonyOS知识库 在上篇文章(HarmonyOS应用开发工具DevEco Studio安装与使用)中我说到官方推出了4.0 Beta版本的IDE&#xff0c;这篇文章就来介绍这个版本的安装与使用 该版本集成了HarmonyOS多…...

网络视频服务器的作用是什么?

随着互联网的快速发展和网络带宽的提升&#xff0c;网络视频已经成为人们日常生活中不可或缺的一部分。网络视频服务器作为支持和传输网络视频的关键基础设施&#xff0c;发挥着重要的作用。本文将以网络视频服务器的作用为方向&#xff0c;探讨其在现代社会中的重要性。 首先…...

解决vue3使用iconpark控制台预警提示问题

前言 最近在项目中使用 iconpark-icon 来管理图标&#xff0c;一切都很顺利&#xff0c;引入链接后&#xff0c;图标正常显示&#xff0c;没有报错。但是控制台却发出了预警信息。 [Vue warn]: Failed to resolve component: iconpark-icon If this is a native custom eleme…...

VMware 虚拟机 NAT 模式网络配置

配置的核心点在于 网关要一致&#xff0c;才能访问外网 比如下面的网关都是&#xff1a;192.168.145.2 问题总结&#xff1a; 当时重启电脑后如果连不上外网了&#xff0c;检查下 windows 服务中 NAT服务是否已经启动...

5-redis高级-哨兵

1 哨兵 1.1 python 操作哨兵 1 哨兵 # 主从---》一主多从-主库用来写-从库用来读-主库挂了--》整个系统就不能写数据了#主从复制存在的问题&#xff1a;1 主从复制&#xff0c;主节点发生故障&#xff0c;需要做故障转移&#xff0c;可以手动转移&#xff1a;让其中一个slave变…...

鸿蒙HarmonyOS4.0开发应用学习笔记

黑马程序员鸿蒙4.0视频学习笔记&#xff0c;供自己回顾使用。1.安装开发工具DevEco Studio 鸿蒙harmony开发文档指南 DevEco Studio下载地址 选择或者安装环境 选择和下载SDK 安装总览 编辑器界面 2.TypeScript语法 2.1变量声明 //string 、number、boolean、any、u…...

联通宽带+老毛子Padavan固件 开启IP v6

联通宽带开启IP v6 参考&#xff1a; 联通宽带开启 IPV6 的方法_联通ipv6怎么开通-CSDN博客 个人宽带如何开启IPv6网络访问 - 知乎 (zhihu.com) 首先&#xff0c;你要确定当前你所在的地区运营商已经开通了IPV6&#xff0c;可以使用手机流量 IP查询(ipw.cn) | IPv6测试 | IPv…...