java集合

java集合类是一种特殊有用的工具类,可以存储数量不等的对象,可以实现常用的数据结构,java集合类还可以用于保存具有映射关系的数组。


java集合的概述

集合用于保存数量不确定的数据,以及保存具有映射关系的数据,java提供集合类,集合类与数组不一样:

数组:可以保存基本数据类型值,也可以是对象

集合:只能保存对象

java集合类主要由两个接口派生而成:Collection和Map

Collection接口,子接口以及实现树:

在这里插入图片描述

Map接口继承树:

在这里插入图片描述

对于Set,List,Queue和Map四种集合类中,最常用的实现类有,HashSet,TreeSet,ArrayList,ArrayDeque,LinkedList,HashMap,TreeMap等实现类


Collection和Iterator接口

Collection接口是List,Set,Queue接口的父接口,该接口定义的方法可用于操作Set集合,List集合,Queue集合。

Collection接口中定义的方法:

在这里插入图片描述

在这里插入图片描述

//使用示例
public class CollectionTest {public static void main(String[] args) {Collection c=new ArrayList();//添加一个元素c.add("孙悟空");//java集合虽然不支持基本类型的值,但是java支持自动装箱c.add(6);System.out.println("c集合个数:"+c.size());//删除指定元素c.remove(6);System.out.println("c集合个数:"+c.size());System.out.println("c集合是否包含孙悟空字符串:"+c.contains("孙悟空"));c.add("Java编程思想");System.out.println("c集合元素:"+c);System.out.println("***************************");Collection books=new HashSet();books.add("HTML");books.add("孙悟空");System.out.println("c集合是否包含books集合?"+c.containsAll(books));//c集合减去books集合里的元素c.removeAll(books);System.out.println("c集合元素:"+c);//删除c集合所有元素c.clear();System.out.println("c集合元素:"+c);//控制books集合里剩下c集合里也包含的元素books.retainAll(c);System.out.println("books集合的元素:"+books);}
}

使用Lambda表达式遍历集合

java8为Iterable接口新增了一个forEach默认方法,该方法所需参数的类型是一个函数式接口,而Iterable接口是Collection接口的父接口,因此Collection集合也可以调用该方法。

public class CollectionEach {public static void main(String[] args) {//创建一个集合Collection books=new HashSet();books.add("java");books.add("anzhuo");books.add("C");//调用forEach方法遍历集合books.forEach(obj-> System.out.println("迭代元素:"+obj));}
}

使用java8增强的Iterator遍历集合元素

Iterator接口是java集合框架的成员,主要用于遍历Collection集合中的元素,Iterator对象也被称为迭代器。

Iterator接口中的4个方法

在这里插入图片描述

public class IteratorTest {public static void main(String[] args) {//创建一个集合Collection books=new HashSet();books.add("java");books.add("anzhuo");books.add("C");Iterator it=books.iterator();while(it.hasNext()){//it.next()方法返回的数据类型是Object类型需要强转String book=(String)it.next();System.out.println(book);if (book.equals("java")){//删除集合上一次next()方法返回的元素it.remove();}//对book变量赋值,不会改变集合元素本身book="SSBBB";}System.out.println(books);}
}

注意:

  1. Iterator仅提供遍历集合,本身并没有提供盛装对象的能力
  2. Iterator必须依附于Collection对象,若有一个Iterator对象,则必然有一个与之关联的Collection对象。
  3. 使用Iterator对集合元素进行迭代时,Iterator并不是把集合元素本身传递给迭代变量,而是把集合元素值传递给迭代变量,所以修改迭代变量值对集合元素本身没有任何影响。
  4. 使用iterator迭代访问Collection集合元素,Collection集合里的元素不能被改变,只能通过Iterator的 remove()方法删除上一次next()方法返回的集合元素才可以,否则会报错

使用Lambda表达式遍历Iterator

java8为Iterator新增了forEachRemaining()方法,该方法所需Consumer参数同样是函数式接口。

public class IteratorEach {public static void main(String[] args) {//创建一个集合Collection books=new HashSet();books.add("java");books.add("anzhuo");books.add("C");//获取books集合对应的迭代器Iterator it=books.iterator();//使用Lambda表达式来遍历集合元素it.forEachRemaining(obj-> System.out.println("迭代集合元素:"+obj));}
}

使用foreach循环遍历集合元素

java5提供的foreach循环迭代访问集合元素更加快捷

public class ForeachTest {public static void main(String[] args) {//创建一个集合Collection books=new HashSet();books.add("java");books.add("anzhuo");books.add("C");for (Object book : books) {//使用强制类型转换System.out.println((String)book);}}
}

注意:使用foreach循环迭代访问集合元素时,该集合不能被改变,否则报异常。


使用java8新增的Predicate操作集合

java8位Collection集合新增了一个removeIf(Predicate filter)方法,该方法将会批量删除复合filter条件的所有元素。Predicate也是函数式接口,所有可以使用Lambda表达式作为参数

//案例
public class PredicateTest2 {public static void main(String[] args) {//创建一个集合Collection books=new HashSet();books.add("java");books.add("anzhuo");books.add("C");//统计包含java子串的图书数量System.out.println(calAll(books,ele->((String)ele).contains("java")));//统计包含C子串的图书数量System.out.println(calAll(books,ele->((String)ele).contains("C")));//统计书名字符串长度大于10的图书数量System.out.println(calAll(books,ele->((String)ele).length()>10));}public static int calAll(Collection books, Predicate p){int total=0;for (Object book : books) {//使用predicate的test方法判断对象是否满足predicate指定的条件if(p.test(book)){total++;}}return total;}
}

使用java8新增Stream操作集合

java8新增了Stream,IntStream,LongStream,DoubleStream等流式API,这些API支持多个支持串行和并行聚集操作的元素。Stream是通用的流接口。每个流式API都提供了Builder来创建对应的流。

在这里插入图片描述

public class IntStreamTest {public static void main(String[] args) {IntStream is= IntStream.builder().add(20).add(13).add(-2).add(18).build();//下面调用聚集方法的代码每次只执行一行// System.out.println("is所有元素的最大值"+is.max().getAsInt());//System.out.println("is所有元素的最小值"+is.min().getAsInt());//System.out.println("is所有元素的和"+is.sum());//System.out.println("is元素的总数"+is.count());// System.out.println("is元素的平均值"+is.average());// System.out.println("is所有元素平方是否都大于20"+is.anyMatch(ele->ele*ele>20));//将is映射成一个新Stream,新Stream的每个元素都是原Stream元素的2倍+1IntStream newIs=is.map(ele->ele*2+1);newIs.forEach(System.out::println);}
}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


Set集合

Set集合不能包含相同的元素,如果试图添加相同的元素在同一个Set集合中,则添加失败,add()方法返回false,且新元素不会加入。


HashSet类

HashSet是Set接口的实现,大多数时候使用Set集合就是使用这个实现类。

HashSet特点:

  1. 不能保证元素排列顺序,顺序可能与添加顺序不同,顺序也可能发生变化
  2. HashSet不是同步,如果多个线程同时访问一个HashSet,则必须通过代码来保证其同步
  3. 集合的元素值可以为null

注意:HashSet集合判断两个元素相等的标准是两个对象通过equals()方法比较相等,并且两个对象的hashCode()方法返回值也相等

//类A的equals方法返回true,没有重写其hashCode方法
class A{@Overridepublic boolean equals(Object obj) {return true;}
}
//类BhashCode方法总返回1,没有重写其equals方法
class B{@Overridepublic int hashCode() {return 1;}
}
//类C的hashCode方法总返回2,重写equals方法返回true
class C{@Overridepublic boolean equals(Object obj) {return true;}@Overridepublic int hashCode() {return 2;}
}
public class HashSetTest {public static void main(String[] args) {HashSet books=new HashSet();//分别向books添加类A,B,C的对象,分别每个添加两个books.add(new A());books.add(new A());books.add(new B());books.add(new B());books.add(new C());books.add(new C());System.out.println(books);}
}

如果把某个类的对象存入HashSet集合中,重写这个类的equals()方法和hashCode()方法时,应该尽量保证两个对象通过equals()方法比较返回true时,hashCode()方法返回值也相等

重写hashCode的基本规则:

  1. 在程序运行中,同一个对象多次调用hashCode()方法应该返回相同的值
  2. 两个对象通过equals()方法比较返回true时,这两个对象的hashCode()方法应该返回相同的值
  3. 对象中用作equals()方法比较标准的实例变量,应该用于计算hashCode值

LinkedHashSet类

LinkedHashSet集合是根据元素的hashCode值决定元素的存储位置,但是同时使用链表维护元素的次序,使得元素看起来以插入的顺序保存。

public class LinkedHashSetTest {public static void main(String[] args) {LinkedHashSet books=new LinkedHashSet();books.add("java");books.add("C");books.add("Go");System.out.println(books);//删除Cbooks.remove("C");//重新添加Cbooks.add("C");System.out.println(books);}
}
/*
结果:
[java, C, Go]
[java, Go, C]
*/

注意:虽然LinkedHashSet使用链表记录集合元素添加顺序,但是LinkedHashSet依然是HashSet,因此依然不允许出现重复的集合元素


TreeSet类

TreeSet是SortedSet接口的实现类,TreeSet可以确保元素处于排序状态。

TerrSet额外提供的几个方法:

在这里插入图片描述

public class TreeSetTest {public static void main(String[] args) {TreeSet nums=new TreeSet();nums.add(5);nums.add(2);nums.add(10);nums.add(-9);//输出集合元素,看到集合元素已经处于排序状态System.out.println(nums);//输出集合元素的第一个元素System.out.println(nums.first());//输出集合元素的最后一个元素System.out.println(nums.last());//返回小于4的集合System.out.println(nums.headSet(4));//返回大于5的子集,如果Set中包含5,子集中也包含5System.out.println(nums.tailSet(5));//返回大于等于-3,小于4的子集System.out.println(nums.subSet(-3,4));}
}
/*
结果:
[-9, 2, 5, 10]
-9
10
[-9, 2]
[5, 10]
[2]
*/

TreeSet采用红黑树d额数据结构存储集合元素,TreeSet支持两种排序方式:

  1. 自然排序

    1. TreeSet会调用集合元素的compareTo(Object obj)方法来比较元素的大小,然后将集合元素按升序排列,这种方式就是自然排序

    2. 如果试图把一个对象添加到TreeSet时,该对象的类必须实现Comparable接口,否则会抛出异常(ClassCastException)。

      实现Comparable接口的常用类:

      • BigDecimal,BigInteger以及所有数值类型对应的包装类:他们按数值的大小进行比较
      • Character:按字符的Unicode值进行比较
      • Boolean:true对应包装类实例大于false对应的包装类实例
      • String:按字符串中字符Unicode值进行比较
      • Date,Time:后面的时间,日期比前面的时间,日期大
    3. TreeSet集合判断两个对象是否相等的唯一标准:两个对象通过compareTo(Object obj)方法比较是否返回0,若是0则他们相等,否则不相等。

      class Z implements Comparable{int age;public Z(int age){this.age=age;}//重写equals()方法,总是返回truepublic boolean equals(Object obj){return true;}//重写compareTo()方法,总是返回1@Overridepublic int compareTo(Object o) {return 1;}
      }
      public class TreeSetTest2 {public static void main(String[] args) {TreeSet set=new TreeSet();Z z1=new Z(6);set.add(z1);//第二次添加同一个对象,输出true表示添加成功System.out.println(set.add(z1));//下面输出set的集合,将看到两个元素System.out.println(set);//修改set集合的第一个元素age变量((Z)set.first()).age=9;//输出set集合的最后一个元素的age变量,将看到是9System.out.println(((Z) set.first()).age);}
      }
      

      TreeSet中添加一个可变对象后 ,并且后面程序修改了该可变对象的实例变量,这将导致他与其他对象的大小顺序发生了改变,但TreeSet不会再次调整他们的顺序,甚至可能导致TreeSet中保存这两个对象通过compareTo(Object obj)方法比较返回0

      class R implements Comparable{int count;public R(int count){this.count=count;}public String toString(){return "R[count:"+count+"]";}//重写equals方法,根据count判断是否相等public boolean equals(Object obj){if(this==obj){return true;}if(obj!=null&&obj.getClass()==R.class){R r=(R)obj;return r.count==this.count;}return false;}//重写compareTo()方法,根据count比较大小@Overridepublic int compareTo(Object obj) {R r=(R)obj;return count > r.count? 1 : count < r.count ? -1 : 0;}
      }public class TreeSetTest3 {public static void main(String[] args) {TreeSet ts=new TreeSet();ts.add(new R(5));ts.add(new R(-3));ts.add(new R(9));ts.add(new R(-2));//打印TreeSet集合,有序排列System.out.println(ts);//取出第一个元素count值R first= (R) ts.first();//对第一个元素count赋值first.count=20;//取出最后一个元素R last= (R) ts.last();//对最后一个元素count赋值,与第二个元素count相同last.count=-2;//再次输出将看到TreeSet里的元素处于无序状态,且有重复System.out.println(ts);//删除实例变量被改变的元素,删除失败System.out.println(ts.remove(new R(-2)));System.out.println(ts);//删除实例变量没有被改变的元素,删除成功System.out.println(ts.remove(new R(5)));System.out.println(ts);}
      }
      

      为了让程序更加健壮,推荐不要修改放入HashSet和TreeSet集合中元素的关键实变量

  2. 定制排序

如果需要实现定制排序,则需要在创建TreeSet集合对象时,提供一个Comparator对象与TreeSet集合关联,由该Comparator对象负责集合元素的排序逻辑。Comparator是一个函数式接口,所以可以使用Lambda表达式来代替Comparator对象

class M{int age;public M(int age){this.age=age;}@Overridepublic String toString() {return "M[age:"+age+"]";}
}public class TreeSetTest4 {public static void main(String[] args) {//用Lambda表达式代替ComparatorTreeSet ts=new TreeSet((o1, o2) ->{M m1= (M) o1;M m2= (M) o2;//根据M对象的age属性来决定大小,age越大,M对象返而越小return m1.age>m2.age?-1:m1.age<m2.age?1:0;} );ts.add(new M(5));ts.add(new M(-30));ts.add(new M(100));System.out.println(ts);}
}

TreeSet判断两个集合元素相等的标准,通过Comparator(或Lambda表达式)比较两个元素返回了0,这样TreeSet不会把第二个元素添加到集合中


EnumSet类

EnumSet 是一个专为枚举设计的集合类,EnumSet中的所有元素都必须是指定枚举类型的枚举值,该枚举类型在创建EnumSet时显式或隐式地指定。

  1. EnumSet的集合元素也是有序的,EnumSet以枚举值在Enum类内的定义顺序来决定集合元素的顺序。
  2. EnumSet在内部以位向量的形式存储,这种存储形式非常紧凑、高效,因此EnumSet对象占用内存很小,而且运行效率很好。尤其是进行批量操作(如调用containsAll()和retainAll()方法)时,如果其参数也是EnumSet集合,则该批量操作的执行速度也非常快。
  3. EnumSet集合不允许加入null元素,如果试图插入null元素,EnumSet将抛出NullPointerException异常。
  4. EnumSet类没有暴露任何构造器来创建该类的实例,程序应该通过它提供的类方法来创建EnumSet对象。
  5. 如果只是想判断EnumSet是否包含null元素或试图删除null元素都不会抛出异常,只是删除操作将返回false,因为没有任何null元素被删除。

方法介绍:

  • EnumSet allOf(Class elementType): 创建一个包含指定枚举类里所有枚举值的EnumSet集合。
  • EnumSet complementOf(EnumSet e): 创建一个其元素类型与指定EnumSet里元素类型相同的EnumSet集合,新EnumSet集合包含原EnumSet集合所不包含的、此类枚举类剩下的枚举值(即新EnumSet集合和原EnumSet集合的集合元素加起来是该枚举类的所有枚举值)。
  • EnumSet copyOf(Collection c): 使用一个普通集合来创建EnumSet集合。
  • EnumSet copyOf(EnumSet e): 创建一个指定EnumSet具有相同元素类型、相同集合元素的EnumSet集合。
  • EnumSet noneOf(Class elementType): 创建一个元素类型为指定枚举类型的空EnumSet。
  • EnumSet of(E first,E…rest): 创建一个包含一个或多个枚举值的EnumSet集合,传入的多个枚举值必须属于同一个枚举类。
  • EnumSet range(E from,E to): 创建一个包含从from枚举值到to枚举值范围内所有枚举值的EnumSet集合。
enum Season{SPRING,SUMMER,FALL,WINTER
}public class EnumSetTest {public static void main(String[] args) {//创建一个EnumSet集合,集合元素就是Season枚举类的全部枚举值EnumSet es1=EnumSet.allOf(Season.class);System.out.println(es1);//创建一个EnumSet空集合,指定其集合元素是Season类的枚举值EnumSet es2=EnumSet.noneOf(Season.class);System.out.println(es2);//手动添加两个元素es2.add(Season.WINTER);es2.add(Season.SPRING);System.out.println(es2);//以指定枚举值创建EnumSet集合EnumSet es3=EnumSet.of(Season.SUMMER,Season.WINTER,Season.FALL);System.out.println(es3);EnumSet es4=EnumSet.range(Season.SUMMER,Season.WINTER);System.out.println(es4);//新创建EnumSet集合元素和es4集合元素相同的类型//es5集合元素+es4集合元素=Season枚举类的全部枚举值EnumSet es5=EnumSet.complementOf(es4);System.out.println(es5);}
}

还可以复制另一个EnumSet集合中所有元素来创建EnumSet集合,或者复制另一个Collection集合中所有的元素来创建新的EnumSet集合。

public class EnumSetTest2 {public static void main(String[] args) {Collection c=new HashSet();c.clear();c.add(Season.FALL);c.add(Season.SPRING);//复制Collection集合中的所有元素来创建EnumSet集合EnumSet enumSet=EnumSet.copyOf(c);System.out.println(enumSet);c.add("java");c.add("C");//下面代码异常,c里面的集合元素不是所有都是枚举类型System.out.println(c);}
}

复制Collection集合里的元素来创建一个EnumSet集合时,必须保证Collection集合里的元素都是同一个枚举类型的枚举值


各Set实现类的性能分析

​ HashSet和TreeSet是Set的两个典型实现,到底如何选择HashSet和TreeSet呢?HashSet的性能总是比TreeSet好,(特别是最常用的添加、查询元素等操作),因为TreeSet需要额外的红黑树算法来维护集合元素的次序。只有当需要一个保持排序的Set时,才应该使用TreeSet,否则都应该使用HashSet.

​ HashSet还有一个子类:LinkedHashSet,对于普通的插入、删除操作,LinkedHashSet比HashSet要略微慢一点,这是由维护链表所带来的额外开销造成的,但由于有了链表,遍历LinkedHashSet会更快。

​ EnumSet是所有Set实现类中性能最好的,但它只能保存同一个枚举类的枚举值作为集合元素。

​ 必须指出的是,Set的三个实现类HashSet、TreeSet和EnumSet都是线程不安全的。如果有多个线程同时访问一个Set集合,并且有超过一个线程修改了该Set集合,则必须手动保证该Set集合的同步性。通常可以通过Collections工具类的synchronizedSortedSet方法来包装该Set集合。此操作最好在创建时进行,以防止对Set集合的意外非同步访问。


List集合

List集合代表一个元素有序,可重复的集合,集合中每个元素都有其对应的顺序索引。


java8改进的List接口和Listterator接口

List作为Collection接口的子接口,当然可以使用Collection接口里的全部方法。由于List是有序集合,因此List集合里增加了根据索引操作集合的方法。

在这里插入图片描述

java8的List接口添加两个默认方法

在这里插入图片描述

public class ListTest {public static void main(String[] args) {List books=new ArrayList();books.add(new String("java"));books.add(new String("C"));books.add(new String("安卓"));//将新字符串对象插入在第二个位置books.add(1,new String("lalalal"));for (int i = 0; i < books.size(); i++) {System.out.println(books.get(i));}//删除第三个元素books.remove(2);System.out.println(books);//判断指定元素在List集合中的位置,输出1,表明位于第二位System.out.println(books.indexOf(new String("安卓")));//将第二个元素替换成新的字符串对象books.set(1,new String("C"));System.out.println(books);//截取books元素中第二个(包含)到第三个(不包含)的集合System.out.println(books.subList(1,2));}
}

java8为Listjihe增加了sort()和replaceAll()两个方法的默认方法,其中sort()方法需要一个Comparator来替换所有集合元素,而replaceAll()方法则需要UnaryOperator来代替所有集合元素,他们都是函数式接口(Comparator和UnaryOperator),所以可以用Lambda表达式作为参数。

public class ListTest2 {public static void main(String[] args) {List books=new ArrayList();books.add(new String("java"));books.add(new String("C"));books.add(new String("安卓"));books.add(new String("IOS"));//使用目标类型为Comparator的Lambda表达式对List集合排序books.sort((o1,o2)->((String)o1).length()-((String)o2).length());System.out.println(books);//使用目标类型为UnaryOperator的Lambda表达式替换集合中所有的元素//该Lambda表达式控制使用每个字符串的长度作为新的集合元素books.replaceAll(ele->((String)ele).length());System.out.println(books);    }
}

List还提供了一个listIterator()方法,该方法返回一个ListIterator对象,ListIterator接口继承Iterator接口,提供了专门的操作。

在这里插入图片描述


ArrayList和Vector实现类

首先两个类都实现了List接口。他们都是有序不唯一的集合,说白了就是存储元素的位置是有序的(每一个元素都以一个对应的索引),相当于一个动态数组

ArrayList和Vector的区别,主要包括两个方面

同步性:

Vector是线程安全的,也就是说它的方法直线是线程同步的,而ArrayList是线程不安全的,它的方法之间是线程不同步的

如果只有一个线程去访问集合那么使用ArrayList,他不考虑线程安全的问题,所以效率会高一些

如果是多个线程去访问集合,那么使用Vector

数据增长性:

ArrayList和Vector集合都有一个初始容量的大小,当元素的个数超过存储容量是,就需要增加ArrayList和Vector的存储空间,每次增加不是

增加一个而是增加多个,Vector是增加原来的两倍,ArrayList没有明文规定,但是从源码中可以看出增长原来的1.5倍

ArrayList和Vector可以设置初始的存储空间的大小,Vector还以设置增长空间大小,而ArrayList不可以。


固定长度的List

通过Arrays工具类中的asList()方法可以把一个数组或者指定对象转换成一个List集合,这个集合不属于ArrayList集合也不是Vector实现类,而是Arrays的内部类ArrayList的实例,可以通用源码查找到这个内部类

public class FixedSizeList {public static void main(String[] args) {List finedList= Arrays.asList("JAVA","C","JAVAEE");//获取finedList的实现类System.out.println(finedList.getClass());//使用该方法引用遍历集合元素finedList.forEach(System.out::println);//试图删除,增加元素,会引发异常finedList.add("JJJ");finedList.remove("JAVA");}
}

Queue集合

Queue集合用于模拟队列这种数据结构,队列通常指 “先进先出”的容器。通常队列不允许随机随机访问队列中的 元素。

Queue接口中的定义的几个方法:

在这里插入图片描述

Queue接口有一个实现类PriorityQueue实现类,除此之外,Queue还有一个Deque接口,Deque代表“双端队列“,双端队列可以从两端进行添加,删除元素。


PriorityQueue实现类

PriorityQueue是一个比较标准的队列实现类,因为PriorityQueue保存队列的元素顺序并不是按照加入队列的顺序,而是按队列元素的大小进行重写排序。从意义上看它违反了队列的基本规则“先进先出”

public class PriorityQueueTest {public static void main(String[] args) {PriorityQueue qp=new PriorityQueue();//插入四个元素qp.add(-1);qp.add(50);qp.add(20);qp.add(0);//输出qp队列System.out.println(qp);//[-1, 0, 20, 50]//访问队列第一个元素,其实就是队列的最小值-1System.out.println(qp.poll());}
}

PriorityQueue的元素排序有两种方式:

在这里插入图片描述


Deque接口与ArrayDeque实现类

Deque接口是Queue接口的子接口,它代表一个双端队列,Deque接口里定义了一些双端队列的方法:

在这里插入图片描述

在这里插入图片描述

Deque接口提供了一个典型的实现类:ArrayDeque,它是一个基于数组实现的双端队列,创建Deque时可以指定一个numElements参数,这个参数用于指定Object[]数组的长度,如果不指定,Deque底层数组长度为16

ArrayDeque作为栈的行为:

public class ArrayDequeStack {public static void main(String[] args) {ArrayDeque stack=new ArrayDeque();//依次将三个元素push入栈stack.push("JAVA");stack.push("C");stack.push("安卓");//输出:[安卓, C, JAVA]System.out.println(stack);//访问diyige元素,但并不将其pop出栈 输出:安卓System.out.println(stack.peek());//依然输出:[安卓, C, JAVA]System.out.println(stack);// pop出第一个元素,输出:安卓System.out.println(stack.pop());//输出:[C, JAVA]System.out.println(stack);}
}

ArrayDeque作为队列的行为:

public class ArrayDequeQueue {public static void main(String[] args) {ArrayDeque queue=new ArrayDeque();//依次将三个元素push入栈queue.offer("JAVA");queue.offer("C");queue.offer("安卓");//输出:[JAVA, C, 安卓]System.out.println(queue);//访问diyige元素,但并不将其pop出栈 输出:JAVASystem.out.println(queue.peek());//依然输出:[JAVA, C, 安卓]System.out.println(queue);// pop出第一个元素,输出:JAVASystem.out.println(queue.poll());//输出:[C, 安卓]System.out.println(queue);}
}

ArrayDeque不仅可以作为栈,也可以作为队列使用


LinkedList实现类

LinkedList类是List接口的实现类,这意味着它是一个List集合,可以根据索引来随机访问集合元素。LinkedList还实现了Deque接口,可以被当成双端队列来使用,因此即可以被当成栈来使用,也可以当成队列来使用。

public class LinkerListTest {public static void main(String[] args) {LinkedList books=new LinkedList();//将字符串添加到队列尾部books.offer("疯狂java");//将一个字符串元素加入栈顶部books.push("javaEE");//将字符串元素添加到队列的头部(相当于栈的顶部)books.offerFirst("Android");//以List方式来遍历集合元素for (int i = 0; i < books.size(); i++) {System.out.println("遍历中:"+books.get(i));}//访问并不删除栈顶的元素System.out.println(books.peekFirst());//访问并不删除队列的最后一个元素System.out.println(books.peekLast());//将栈顶元素弹出栈System.out.println(books.pop());//下面输出队列中第一个元素被删除System.out.println(books);//访问并删除队列的最后一个元素System.out.println(books.pollLast());//下面输出:[javaEE]System.out.println(books);}
}

LinkedList内部以链表的形式来保存集合中的元素,因此随机访问集合元素时性能较差,但在插入,删除元素时性能比较出色。


各种线性表的性能分析

Java提供的List就是一个线性表接口,而ArrayList、LinkedList又是线性表的两种典型的实现;基于数组的线性表和基于链的线性表。Queue代表了队列,Deque代表了双端队列(既可作为队列使用,也可以作为栈使用),接下来对各种实现类的性能进行分析。

​ 初学者可以无须理会ArrayList和LinkedList之间的性能差异,只需要知道LinkedList集合不仅提供了List的功能,还提供了双端队列、栈的功能就行。但对于一个成熟的Java程序员,在一些性能非常敏感的地方,可能需要慎重选择哪个List实现。

​ 一般来说,由于数组以一块连续内存区来保存所有的数组元素,所以数组在随机访问时性能最好,所有的内部以数组作为底层实现的集合在随机访问时性能都比较好;而内部以链表作为底层实现的集合在执行插入、删除操作时有较好的性能。但总体来说,ArrayList的性能比LinkedList的性能要好,因此大部分时候都应该考虑使用ArrayList。

​ 关于使用List集合有如下建议:

如果需要遍历List集合元素,对于ArrayList、Vector集合,应该使用随机访问方法(get)来遍历集合元素,这样性能更好;对于LinkedList集合,则应该采用迭代器(Iterator)来遍历集合元素。

如果需要经常执行插入、删除操作来改变包含大量数据的List集合的大小,可考虑使用LinedList集合。使用ArrayList、Vector集合可能需要经常重新分配内部数组的大小,效果可能较差。

如果有多个线程需要同时访问List集合中的元素,开发者可考虑使用Collections将集合包装成线程安全的集合。


java8增强的Map集合

Map用于保存具体有映射关系的数据,因此Map集合里保存着两组值,一组值用于保存Map里的key,另外一组值用于保存Map里的value,key和value都可以是任何引用类型的数据。Map的key不允许重复,即同一个Map对象的任何两个key通过equals方法比较总是返回false。

key和value关系:

​ key和value之间存在单向一对一关系,即通过指定的key,总能找到唯一的,确定的value。从Map中取出数据时,只要给出指定的key,就可以取出对应的数据时。如果把Map的两组值拆开来看,Map里的所有key组成了一个set集合(所有的key是没有顺序的,key与key之间不能重复)。
​ 如果把Map里的所有value放在一起来看,它们类似于一个List,元素与元素之间可以重复,每个元素可以根据索引来查找,只是Map中的索引不再是整数值,而是以另一个对象作为所用。

Map接口定义如下常用方法:

在这里插入图片描述

在这里插入图片描述

public class MapTest {public static void main(String[] args) {Map map=new HashMap();map.put("疯狂java",109);map.put("疯狂IOS",10);map.put("疯狂Ajax",79);//多次放入key-value对的value可以重复map.put("JAVAEE",99);//放入重复的key时,新的value会覆盖原有的vlaue//如果新的value覆盖了原有的value,该方法会返回被覆盖(原来)的value值System.out.println(map.put("疯狂IOS",100));System.out.println(map);//输出map包含4个key-value对//判断是否包含指定keySystem.out.println("是否包含疯狂IOS的key:"+map.containsKey("疯狂IOS"));//判断是否包含指定valueSystem.out.println("是否包含值为99的value:"+map.containsValue(99));//获取Map集合的所有key组合的集合,通过遍历key来实现遍历所有key-value对for (Object key : map.keySet()) {//map.get(key)方法获取指定key对应的valueSystem.out.println(key+"-->"+map.get(key));}map.remove("疯狂java");//根据key来删除key-value对System.out.println(map);//输出结果中不在包含疯狂java=109的key-value对}
}

java8为Map新增的方法

查看API


java8改进的HashMap和Hashtable实现类

HashMap和Hashtable的两个典型区别:

  1. Hashtable是一个线程安全的Map实现,而HashMap是一个线程不安全的实现,所以HashMap性能会比Hashtable性能好一些,但如果多个线程访问一同一个Map对象时,使用Hashtable会更好
  2. Hashtable不允许使用null作为Key和value,但HashMap可以使用null作为key和value,不过key-value的key只能由一个作为null值,而value可以是无限个
public class NullInHashMap {public static void main(String[] args) {HashMap hm=new HashMap();//试图将两个key为null值的key-value对放入HashMap中hm.put(null,null);hm.put(null,null);//将一个value为null值的key-value对放入HashMap中hm.put("A",null);//输出hm对象System.out.println(hm);//{null=null, A=null}}
}

为了能成功在HashMAp和Hashtable中存储,获取对象,作用key的对象必须实现HashCode()方法和equals()方法。

  1. HashSet,HashMap,Hashtable判断两个key相等的标准是:两个key通过equals()方法比较返回true,两个key的hashCode值也相等
  2. HashMap,Hashtable中包含一个containsValue()方法,用于判断包含指定value。HashMap,Hashtable判断两个value相等的标准:只需要通过两个对象的equals()方法比较返回true即可
class A{int count;public A(int count){this.count=count;}//根据count的值来判断两个对象是否相等public boolean equals(Object obj){if(obj==this){return true;}if(obj!=null&&obj.getClass()==A.class){A a= (A) obj;return this.count==a.count;}return false;}//根据count来计算hashCode值public int hashCode(){return this.count;}
}
class B{//重写equals方法,B对象与任何对象通过equals()方法比较抖返回truepublic boolean equals(Object obj){return true;}
}
public class HashtableTest {public static void main(String[] args) {Hashtable ht=new Hashtable();ht.put(new A(6000),"疯狂java");ht.put(new A(87352),"JAVAEE");ht.put(new A(1235),new B());System.out.println(ht);//只要两个对象同equals()方法比较返回true//Hashtable就认为他们的vlaue相等//由于Hashtable中有一个B对象//它与任何对象通过equals()方法比较都相等,所有下面输出trueSystem.out.println(ht.containsValue("测试字符串"));//输出true//只要两个对象的hashCode值相等,他们通过equals()方法比较就会返回true,且hashCode值相等//Hashtable即认为他们是相同的key,所以下面输出trueSystem.out.println(ht.containsValue(new A(87352)));//下面语句删除最后一个key-value对ht.remove(new A(1235));System.out.println(ht);}
}

注意:与HashSet类似,尽量不要使用可变对象作为HashMap,Hashtable的key。


LinkedHashMap实现类

LinkedHashMap是HashMap的子类,是一个可以使用双向链表来维护的key-value对的次序,该链表负责维护Map的迭代顺序,迭代顺序与key-value对的插入顺序保持一致。

public class LinkedHashMapTest {public static void main(String[] args) {LinkedHashMap scores=new LinkedHashMap();scores.put("语文",80);scores.put("数学",100);scores.put("英语",27);//调用forEach()方法变量scores里的所有key-value对scores.forEach((key,value)-> System.out.println(key+"--->"+value));}
}
/*
结果:
语文--->80
数学--->100
英语--->27
*/

使用Properties读写属性文件

Properties类是Hashtable类的子类,该对象在处理属性文件时特别方便。Properties类可以把Map对象和属性文件关联起来,从而可以吧Map对象中的key-value对写入属性文件中,可以把属性文件中的“属性名=属性值”加载到Map对象中。

Properties类提供了三个方法修改里面的key,value值

在这里插入图片描述

在这里插入图片描述

public class PropertiesTest {public static void main(String[] args) throws Exception {Properties proper=new Properties();//向Properties中添加对象proper.setProperty("username","yeeku");proper.setProperty("password","123456");//将Properties中key-value对保存到a.ini文件中proper.store(new FileOutputStream("a.ini"),"comment line");//新建一个Properties对象Properties proper2=new Properties();//向proper2添加属性proper2.setProperty("gender","male");//将a.ini文件中的key-value对追加到proper2中proper2.load(new FileInputStream("a.ini"));System.out.println(proper2);}
}

SortedMap接口和TreeMap实现类

SortedMap接口是Map接口的子接口,SortedMap接口中有一个TreeMap实现类。它是一个红黑树数据结构,每个key-value对作为红黑树的一个节点。TreeMap存储key-value对时,需要根据key对节点进行排序。

两种排序方式:

  1. 自然排序:TreeMap的所有key必须实现Comparable接口,而且所有的key应该是同一个类的对象,否则抛出异常
  2. 定制排序:创建TreeMap时,传入一个Comparator对象,该对象负责对TreeMap中的所有key进行排序。采用定制排序时不要求Map的key实现Comparable接口

在这里插入图片描述

class R implements Comparable{int count;public R(int count){this.count=count;}public String toString(){return "R[count:"+count+"]";}//根据count来判断两个对象是否相等public boolean equals(Object obj){if(this==obj){return true;}if(obj!=null&& obj.getClass()==R.class){R r= (R) obj;return r.count==this.count;}return false;}//根据count属性值来判断两个对象大小public int compareTo(Object obj){R r= (R) obj;return count>r.count?1:count<r.count?-1:0;}}public class TreeMapTest {public static void main(String[] args) {TreeMap tm=new TreeMap();tm.put(new R(3),"轻量级开发JAVAEE");tm.put(new R(-5),"疯狂java");tm.put(new R(9),"疯狂安卓");System.out.println(tm);//返回该TreeMap的第一个Entry对象System.out.println(tm.firstEntry());//返回该TreeMap的对吼一个key值System.out.println(tm.lastKey());//返回TreeMap的new R(2)大的最小key值System.out.println(tm.higherKey(new R(2)));//返回该TreeMap的比new R(2)小的最大键值对System.out.println(tm.lowerEntry(new R(2)));//返回该TreeMap的子TreeMapSystem.out.println(tm.subMap(new R(-1),new R(4)));}
}
/*
结果:
{R[count:-5]=疯狂java, R[count:3]=轻量级开发JAVAEE, R[count:9]=疯狂安卓}
R[count:-5]=疯狂java
R[count:9]
R[count:3]
R[count:-5]=疯狂java
{R[count:3]=轻量级开发JAVAEE}
*/

WeakHashMap实现类

WeakHashMap与HashMap的用法基本类似。

区别:

  1. WeakHashMap:对key只保留弱引用,如果key所引用的对象没有被其他强引用变量所引用,这些key所引用对象则会被垃圾回收,WeakHashMap也可能会自动删除这些key所对应的key-value对
  2. HashMap:对key保留对实际对象的强引用,该HahsMap的所有key所引用的对象就不会被垃圾回收,也不会自动删除key所对应的key-value值
public class WeakHashMapTest {public static void main(String[] args) {WeakHashMap whm=new WeakHashMap();whm.put(new String("语文"),new String("良好"));whm.put(new String("数学"),new String("及格"));whm.put(new String("英语"),new String("优秀"));//向WeakHashMap添加键值对//该key是一个系统缓存字符串对象whm.put("java",new String("中等"));//输出System.out.println(whm);//通知系统立即进行垃圾回收System.gc();System.runFinalization();//通常情况下,将只看到一个键值对System.out.println(whm);}
}

​ 当系统进行垃圾回收时,删除了WeakHashMap对象的前三个键值对。这是因为这三个key都是匿名的字符串对象,只保留了他们的弱引用,这样垃圾回收时会自动删除这三个键值对。
​ WeakHashMap对象的第四个键值对的key是一个字符串直接量(系统会自动保留该字符串对象的强引用),所以垃圾回收时不会回收它


IdentityHashMap实现类

在IdentityHashMap中,当且仅当两个key严格相等时,才会认为两个key相等。

public class IdentityHashMapTest {public static void main(String[] args) {IdentityHashMap ihm=new IdentityHashMap();//下面会向ihm对象中添加两个键值对ihm.put(new String("语文"),89);ihm.put(new String("语文"),79);//下面会向ihm对象中添加一个键值对ihm.put("java",99);ihm.put("java",100);System.out.println(ihm);}
}
//结果:{java=100, 语文=89, 语文=79}

​ 上面程序向IdentityHashMap对象中添加4个键值对,前两个键值对的key是新创建的字符串对象,通过比较不相等,所以IdentityHashMap会把他们当成2个key来处理;后两个键值对中key是字符串直接量,他们的字符序列完全相同,所以通过比较返回true,因此只有一次可以添加成功。


EnumMap实现类

EnumMap是一个与枚举类一起使用的Map实现,在EnumMap中的所有key都必须是单个枚举类的枚举值。创建时必须显式或隐式的指定它对应的枚举类。

特征:

  1. 在内部以数组的形式保存,所以这种实现形式非常紧凑,高效。
  2. 根据key自然排序来维护键值对的顺序。
  3. 不允许使用null作为key,但允许使用null作为value。
enum Season{SPRING,SUMMER,FALL,WINTER
}
public class EunmMapTest {public static void main(String[] args) {//创建EnumMap对象,所有key都是枚举类的枚举值EnumMap em=new EnumMap(Season.class);em.put(Season.SUMMER,"炎炎夏日");em.put(Season.SPRING,"春暖花开");System.out.println(em);}
}
//结果:{SPRING=春暖花开, SUMMER=炎炎夏日}

各Map实现类的性能分析

在这里插入图片描述


HashSet和HashMap的性能选项

HashSet,HashMapd的hash表包含如下属性:

  1. 容量:hash表中桶的数量
  2. 初始化容量:创建hash表时桶的数量。
  3. 尺寸:当前hash表中记录的数量
  4. 负载因子:负载因子等于“size/capacity”

在这里插入图片描述


操作集合工具类:Collections

java提供了一个操作List,Set,Map的集合的工具类,Collections,该工具类提供了大量的方法,对集合进行排序,查询,修改等操作。


排序操作

在这里插入图片描述

public class SortTest {public static void main(String[] args) {ArrayList nums=new ArrayList();nums.add(2);nums.add(-5);nums.add(3);nums.add(0);System.out.println(nums);Collections.reverse(nums);//次序反转System.out.println(nums);Collections.sort(nums);//自然排序System.out.println(nums);Collections.shuffle(nums);//随机排序System.out.println(nums);}
}

查找,替换操作

在这里插入图片描述

public class SearchTest {public static void main(String[] args) {ArrayList nums=new ArrayList();nums.add(-5);nums.add(2);nums.add(3);nums.add(0);System.out.println(nums);System.out.println(Collections.max(nums));//输出最大的值System.out.println(Collections.min(nums));//输出最小的值Collections.replaceAll(nums,0,1);//将nums中的0替换成1System.out.println(nums);//判断-5在List集合中出现的次数System.out.println(Collections.frequency(nums,-5));Collections.sort(nums);//对集合进行排序System.out.println(nums);//只有排序后的List集合才可以使用二分查找System.out.println(Collections.binarySearch(nums, 3));}
}
/*
结果:
[-5, 2, 3, 0]
3
-5
[-5, 2, 3, 1]
1
[-5, 1, 2, 3]
3
*/

同步控制

Collections类提供了多个synchronizedXxx()方法,该方法可以将指定集合包装成线程同步的集合,从而解决多线程并发访问集合的线程安全

public class synchronizedTest {public static void main(String[] args) {//创建4个线程安全的对象Collection c=Collections.synchronizedCollection(new ArrayList<>());List list=Collections.synchronizedList(new ArrayList<>());Set s=Collections.synchronizedSet(new HashSet<>());Map m=Collections.synchronizedMap(new HashMap<>());}
}

设置不可变集合

在这里插入图片描述

public class UnmodifiableTest {public static void main(String[] args) {//创建一个空的,不可变的List对象List unmodifiableList = Collections.emptyList();//创建一个只有一个元素,且不能改变的Set集合Set unmodifiableSet=Collections.singleton("疯狂java");//创建一个普通的Map对象Map scores=new HashMap();scores.put("语文",80);scores.put("java" ,100);//返回普通的Map对象对应的不可变版本Map unmodifiableMap=Collections.unmodifiableMap(scores);//下面的操作会发生异常unmodifiableList.add("测试");unmodifiableSet.add("语文测试");unmodifiableMap.put("语文",10000);}
}

繁琐的接口:Enumeration

Enumeration接口是Iterator迭代器的”古老版本”,从JDK1.0开始, Enumeration接口就已经存在了( IteratorJDK1.2才出现)。 Enumeration接口只有两个名字很长的方法。

方法 描述
boolean hasMoreElements() 如果此迭代器还有剩下的元素,则返回true
Object nextElement() 返回该迭代器的下一个元素,如果还有的话(否则抛出异常)。

通过这两个方法不难发现, Enumeration接口中的方法名称冗长,难以记忆,而且没有提供Iteratorremove方法。如果现在编写Java程序,应该尽量采用Iterator迭代器,而不是用Enumeration迭代器

不推荐使用Enumeration:

Java之所以保留Enumeration接口,主要是为了照顾以前那些”古老”的程序,那些程序里大量使用了Enumeration接口,如果新版本的Java里直接删除Enumeration接口,将会导致那些程序全部出错。在计算机行业有一条规则:加入任何规则都必须慎之又慎,因为以后无法删除规则。
实际上,前面介绍的Vector(包括其子类Stack)Hashtable两个集合类,以及另一个极少使用的Bitset,都是从JDK1.0遗留下来的集合类,而Enumeration接口可用于遍历这些”古老”的集合类。
而对于ArrayListHashMap等集合类,已经不支持Enumeration迭代器了。

素,且不能改变的Set集合
Set unmodifiableSet=Collections.singleton(“疯狂java”);
//创建一个普通的Map对象
Map scores=new HashMap();
scores.put(“语文”,80);
scores.put(“java” ,100);
//返回普通的Map对象对应的不可变版本
Map unmodifiableMap=Collections.unmodifiableMap(scores);
//下面的操作会发生异常
unmodifiableList.add(“测试”);
unmodifiableSet.add(“语文测试”);
unmodifiableMap.put(“语文”,10000);
}
}


---### 繁琐的接口:EnumerationEnumeration接口是Iterator迭代器的”古老版本”,从JDK1.0开始, Enumeration接口就已经存在了( `Iterator`从`JDK1.2`才出现)。 Enumeration接口只有两个名字很长的方法。| 方法                        | 描述                                                  |
| :-------------------------- | :---------------------------------------------------- |
| `boolean hasMoreElements()` | 如果此迭代器还有剩下的元素,则返回`true`。             |
| `Object nextElement()`      | 返回该迭代器的下一个元素,如果还有的话(否则抛出异常)。 |通过这两个方法不难发现, `Enumeration`接口中的方法名称冗长,难以记忆,而且没有提供`Iterator`的`remove`方法。**如果现在编写`Java`程序,应该尽量采用`Iterator`迭代器,而不是用`Enumeration`迭代器**。**不推荐使用Enumeration:**`Java`之所以保留`Enumeration`接口,主要是为了照顾以前那些”古老”的程序,那些程序里大量使用了`Enumeration`接口,如果新版本的`Java`里直接删除`Enumeration`接口,将会导致那些程序全部出错。在计算机行业有一条规则:加入任何规则都必须慎之又慎,因为以后无法删除规则。
实际上,前面介绍的`Vector`(包括其子类`Stack)`、 `Hashtable`两个集合类,以及另一个极少使用的`Bitset`,都是从`JDK1.0`遗留下来的集合类,而`Enumeration`接口可用于遍历这些”古老”的集合类。
而对于`ArrayList`、 `HashMap`等集合类,已经不支持`Enumeration`迭代器了。**除非在某些极端情况下,不得不使用`Enumeration`,否则都应该选择`Iterator`迭代器**
查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 倒计时(刷新重新计时)JS(附部分代码)

    倒计时——每次刷新重新倒计时知识点步骤运行结果script代码段Body代码段 知识点 DOM操作 定时器函数 格式化时间 步骤 一、获取操作对象DOM标签 二、格式化时间的函数方法 1、设定倒计时时间长度:天、时、分、秒2、计算该时间长度的总秒数:时*3600+分*60+秒;3、格式化时间:…...

    2024/5/4 19:00:53
  2. springboot启动报错Error starting ApplicationContext

    springboot启动报错Error starting ApplicationContext. To display the conditions report re-run your application with debug enabled后来发现是配置文件里面数据库连接配置有错误...

    2024/5/4 18:18:25
  3. 图像处理100题(11-20)

    11.均值滤波: import cv2 import numpy as np #Mean filter def mean_filter(img,K_size=3):if len(img.shape) == 3:H,W,C = img.shapeelse:H,W,C = np.expand_dims(img,axis=-1)H,W,C = img.shape#zero paddingpad = K_size//2out = np.zeros((H+pad*2,W+pad*2,C),dtype=np.…...

    2024/5/4 18:23:06
  4. CSS层叠样式表笔记(一)

    CSS CSS简介 CSS时层叠样式表( Cascading Style Sheets )的简称. CSS也是一种标记语言 CSS 规则由两个主要的部分构成:选择器以及一条或多条声明。选择器是用于指定 CSS 样式的 HTML 标签,花括号内是对该对象设置的具体样式 属性和属性值以“键值对”的形式出现 属性是对指定…...

    2024/5/4 22:59:24
  5. 无法在代理后面下载Docker镜像

    本文翻译自:Cannot download Docker images behind a proxy I installed Docker on my Ubuntu 13.10 (Saucy Salamander) and when I type in my console: 我在我的Ubuntu 13.10(Saucy Salamander)上安装了Docker,当我输入我的控制台时: sudo docker pull busyboxI get t…...

    2024/5/4 23:36:43
  6. Object类---clone()方法---finalize()方法---getClass()方法---hashcode()方法---toString()方法---equals()方法

    Object类 API—Application Programming Interfaces(提供一系列的接口以及接口下的类) API里提供的所有方法要么是被protected修饰要么就是不写(public) 1.概念 Object类是java的顶级父类,每个类默认继承Object类。2.重要方法 1.clone():把原对象的属性值赋值到新对象中并…...

    2024/5/4 23:51:43
  7. elasticsearch解决控制台中文乱码问题

    elasticsearch解决控制台中文乱码问题参考文章: (1)elasticsearch解决控制台中文乱码问题 (2)https://www.cnblogs.com/chenmz1995/p/10528060.html 备忘一下。...

    2024/5/5 0:56:54
  8. excel中在公式中实现单元格内换行

    在公式中加入CHAR(10),使用&连接。一般情况下,还要用&与公式的其他部分连接。同时单元格要设置成自动换行。比如=A1&CHAR(10)&B1...

    2024/5/5 0:17:24
  9. 你不知道的LinkedList(二):LinkedList的增删操作真的会比ArrayList快吗

    十年前,在刚解除java不久,面试中就有人问道LinkedList和ArrayList的区别。我记得当时普片的答案都说是,LinikedList底层基于链表实现。而ArrayList底层基于数据。因此LinkedList的查找操作比ArrayList慢,但是增删等操作由于不需要移动数据,因此会比ArrayList快。但是事实上…...

    2024/5/4 21:19:15
  10. HTTP相关面试题

    http协议相关面试题 1、游览器输入一个地址。到页面展示中间经历了哪些东西? 这个问题前端面试基本上百分百问的。测试的话,基础的功能面试可能不会问。自动化的话基本上也会问的。 1、游览器输入url。先解析url地址是否合法 2、游览器检查是否有缓存(游览器缓存-系统缓存-路…...

    2024/5/5 0:18:19
  11. jvm-018(张龙老师jvm教程) 类的命名空间与卸载详解

    一、类加载器的命名空间每个类加载器都有自己的命名空间,命名空间由该类加载器及其所有父类加载器所加载的类组成。同一个命名空间中,不会出现类的完整名字(包括类的包名)相同的两个类。在不同的命名空间中,有可能出现类的完整名字(包括类的包名)相同的两个类。 二、类的…...

    2024/5/5 8:23:51
  12. 消息中间件-RabbitMQ

    消息队列应用场景消息中间件概述RabbitMQ 概念一个客户端只与消息中间件建立一条链接(长连接),一条链接里面有多个channel(虚拟链接,复用一条TCP连接) 虚拟主机是rabbitmq为了隔离不同类型客户端出现的概念。我们在开发过程中可以一个客户端一个虚拟主机。即一个rabbitmq…...

    2024/5/4 15:36:26
  13. 精通Git

    精通Git下载地址: https://pan.baidu.com/s/12kJefrDUhvsPhvfBug2VEA扫码下面二维码关注公众号回复100012 获取分享码本书目录结构如下:ProGit. . . . . . . . . . . . . . . . . . . . . . 1Scott Chacon 序 . . . . . . . . . . . . . . . . . . . . . 2Ben Straub 序 . .…...

    2024/5/5 13:04:44
  14. 整理使用RecyclerView控件在长按删除事件中的用法(使用Kotlin)

    一、前言: 在最近的学习中,使用Recyclerview控件时,遇到需要长按删除的场景,在测试过程中,遇到各种崩溃,在这里总结一下: 在本博客汇中,使用了一个统计学生信息的demo,并且用到了SQLite,这样保证长按删除的同时数据库也能同步数据,先上一下长按删除的效果图:二、代…...

    2024/5/5 0:05:52
  15. SV并发线程

    写在前面:冲冲冲Verilog典型的并发语句集合initial语句:在整个仿真时间内只执行一次, initial语句都是并发的always语句:可以对组合电路和时序电路进行建模, always语句都是并发的assign语句:可以对组合电路进行建模, assign语句都是并发的beginend:语句从上往下,顺序…...

    2024/5/4 19:08:17
  16. HANA数据库恢复体验

    刚才一个开发人员告诉我,他删除了一个SAP标准功能。 评估后,我开始恢复开发环境到今天早上8:00,只用了5分钟不到,他再次进入系统,SAP标准功能回来了。这就是HANA,试问DB2,ORACLE管理有这么方便吗?...

    2024/5/5 16:11:13
  17. Vue X入门

    Vue X入门安装使用导入项目在项目中使用 安装 使用NPM安装 npm install vuex --save使用Yarn安装 yarn add vuex使用 导入项目 在项目src目录下创建store文件夹,并在该文件夹中创建index.js打开index.js 导入vuex 并用vue使用它 import Vue from vue import Vuex from vuexVue…...

    2024/5/5 21:29:20
  18. 前端-ES6

    一、简介 ES6, 全称 ECMAScript 6.0 ,是 JavaScript 的下一个版本标准,2015.06 发版。 ES6 主要是为了解决 ES5 的先天不足,比如 JavaScript 里并没有类的概念,但是目前浏览器的 JavaScript 是 ES5 版本,大多数高版本的浏览器也支持 ES6,不过只实现了 ES6 的部分特性和功…...

    2024/5/6 0:46:52
  19. js中[]、{}、()区别

    一、{ } 大括号,表示定义一个对象,大部分情况下要有成对的属性和值,或是函数体{}表示对象、[]表示对象的属性、方法,()如果用在方法名后面,代表调用如:var LangShen = {"Name":"Langshen","AGE":”28”}; 上面声明了一个名为“LangShen”的…...

    2024/5/6 5:21:28
  20. 揭秘快手直播带货网红KOL/大V们满满的赚钱套路!

    今年是直播带货的元年,风口流量特别大,尤其是快手直播在电商带货发展趋势也是不断发展壮大。你羡慕薇娅们、辛有志为首的818家族、韩国媳妇大璐璐们的那么,让我们一起来揭秘这些快手直播带货大V们成功的秘诀是什么吧!一、新玩法去年大家都在谈私域流量,今年则是直播带货,…...

    2024/5/6 3:43:17

最新文章

  1. 通讯录项目—顺序表实现

    在上次我介绍顺序表后相信大家对顺序表有了一定的了解&#xff0c;现在就让我们来练练如何用它&#xff0c;这篇是在顺序表基础上新增的(建议看看线性表—顺序表实现-CSDN博客)。 目录 通讯录简介 创建用户信息 适配和理解通讯录 功能实现 初始化通讯录 销毁通讯录 增加…...

    2024/5/8 22:07:30
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/5/7 10:36:02
  3. 腾讯云轻量服务器流量不够用了会怎么样?

    腾讯云轻量应用服务器是限制月流量的&#xff0c;如果当月流量不够用了&#xff0c;流量超额了怎么办&#xff1f;流量超额后&#xff0c;需要另外支付流量费&#xff0c;如果你的腾讯云账号余额&#xff0c;就会自动扣除对应的流量费&#xff0c;如果余额不足&#xff0c;轻量…...

    2024/5/8 8:45:36
  4. 《c++》多态案例一.电脑组装

    一.代码展示 #include <iostream> using namespace std; class CPU { public://抽象计算函数virtual void calculate() 0;};class CVideoCard { public://抽象显示函数virtual void display() 0;}; class Memory { public://抽象存储函数virtual void storage() 0;};…...

    2024/5/5 8:48:19
  5. 416. 分割等和子集问题(动态规划)

    题目 题解 class Solution:def canPartition(self, nums: List[int]) -> bool:# badcaseif not nums:return True# 不能被2整除if sum(nums) % 2 ! 0:return False# 状态定义&#xff1a;dp[i][j]表示当背包容量为j&#xff0c;用前i个物品是否正好可以将背包填满&#xff…...

    2024/5/8 19:32:33
  6. 【Java】ExcelWriter自适应宽度工具类(支持中文)

    工具类 import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet;/*** Excel工具类** author xiaoming* date 2023/11/17 10:40*/ public class ExcelUti…...

    2024/5/7 22:31:36
  7. Spring cloud负载均衡@LoadBalanced LoadBalancerClient

    LoadBalance vs Ribbon 由于Spring cloud2020之后移除了Ribbon&#xff0c;直接使用Spring Cloud LoadBalancer作为客户端负载均衡组件&#xff0c;我们讨论Spring负载均衡以Spring Cloud2020之后版本为主&#xff0c;学习Spring Cloud LoadBalance&#xff0c;暂不讨论Ribbon…...

    2024/5/8 1:37:40
  8. TSINGSEE青犀AI智能分析+视频监控工业园区周界安全防范方案

    一、背景需求分析 在工业产业园、化工园或生产制造园区中&#xff0c;周界防范意义重大&#xff0c;对园区的安全起到重要的作用。常规的安防方式是采用人员巡查&#xff0c;人力投入成本大而且效率低。周界一旦被破坏或入侵&#xff0c;会影响园区人员和资产安全&#xff0c;…...

    2024/5/8 20:33:13
  9. VB.net WebBrowser网页元素抓取分析方法

    在用WebBrowser编程实现网页操作自动化时&#xff0c;常要分析网页Html&#xff0c;例如网页在加载数据时&#xff0c;常会显示“系统处理中&#xff0c;请稍候..”&#xff0c;我们需要在数据加载完成后才能继续下一步操作&#xff0c;如何抓取这个信息的网页html元素变化&…...

    2024/5/8 1:37:39
  10. 【Objective-C】Objective-C汇总

    方法定义 参考&#xff1a;https://www.yiibai.com/objective_c/objective_c_functions.html Objective-C编程语言中方法定义的一般形式如下 - (return_type) method_name:( argumentType1 )argumentName1 joiningArgument2:( argumentType2 )argumentName2 ... joiningArgu…...

    2024/5/7 16:57:02
  11. 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】

    &#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】&#x1f30f;题目描述&#x1f30f;输入格…...

    2024/5/7 14:58:59
  12. 【ES6.0】- 扩展运算符(...)

    【ES6.0】- 扩展运算符... 文章目录 【ES6.0】- 扩展运算符...一、概述二、拷贝数组对象三、合并操作四、参数传递五、数组去重六、字符串转字符数组七、NodeList转数组八、解构变量九、打印日志十、总结 一、概述 **扩展运算符(...)**允许一个表达式在期望多个参数&#xff0…...

    2024/5/8 20:58:56
  13. 摩根看好的前智能硬件头部品牌双11交易数据极度异常!——是模式创新还是饮鸩止渴?

    文 | 螳螂观察 作者 | 李燃 双11狂欢已落下帷幕&#xff0c;各大品牌纷纷晒出优异的成绩单&#xff0c;摩根士丹利投资的智能硬件头部品牌凯迪仕也不例外。然而有爆料称&#xff0c;在自媒体平台发布霸榜各大榜单喜讯的凯迪仕智能锁&#xff0c;多个平台数据都表现出极度异常…...

    2024/5/7 21:15:55
  14. Go语言常用命令详解(二)

    文章目录 前言常用命令go bug示例参数说明 go doc示例参数说明 go env示例 go fix示例 go fmt示例 go generate示例 总结写在最后 前言 接着上一篇继续介绍Go语言的常用命令 常用命令 以下是一些常用的Go命令&#xff0c;这些命令可以帮助您在Go开发中进行编译、测试、运行和…...

    2024/5/8 1:37:35
  15. 用欧拉路径判断图同构推出reverse合法性:1116T4

    http://cplusoj.com/d/senior/p/SS231116D 假设我们要把 a a a 变成 b b b&#xff0c;我们在 a i a_i ai​ 和 a i 1 a_{i1} ai1​ 之间连边&#xff0c; b b b 同理&#xff0c;则 a a a 能变成 b b b 的充要条件是两图 A , B A,B A,B 同构。 必要性显然&#xff0…...

    2024/5/7 16:05:05
  16. 【NGINX--1】基础知识

    1、在 Debian/Ubuntu 上安装 NGINX 在 Debian 或 Ubuntu 机器上安装 NGINX 开源版。 更新已配置源的软件包信息&#xff0c;并安装一些有助于配置官方 NGINX 软件包仓库的软件包&#xff1a; apt-get update apt install -y curl gnupg2 ca-certificates lsb-release debian-…...

    2024/5/8 18:06:50
  17. Hive默认分割符、存储格式与数据压缩

    目录 1、Hive默认分割符2、Hive存储格式3、Hive数据压缩 1、Hive默认分割符 Hive创建表时指定的行受限&#xff08;ROW FORMAT&#xff09;配置标准HQL为&#xff1a; ... ROW FORMAT DELIMITED FIELDS TERMINATED BY \u0001 COLLECTION ITEMS TERMINATED BY , MAP KEYS TERMI…...

    2024/5/8 1:37:32
  18. 【论文阅读】MAG:一种用于航天器遥测数据中有效异常检测的新方法

    文章目录 摘要1 引言2 问题描述3 拟议框架4 所提出方法的细节A.数据预处理B.变量相关分析C.MAG模型D.异常分数 5 实验A.数据集和性能指标B.实验设置与平台C.结果和比较 6 结论 摘要 异常检测是保证航天器稳定性的关键。在航天器运行过程中&#xff0c;传感器和控制器产生大量周…...

    2024/5/7 16:05:05
  19. --max-old-space-size=8192报错

    vue项目运行时&#xff0c;如果经常运行慢&#xff0c;崩溃停止服务&#xff0c;报如下错误 FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 因为在 Node 中&#xff0c;通过JavaScript使用内存时只能使用部分内存&#xff08;64位系统&…...

    2024/5/8 1:37:31
  20. 基于深度学习的恶意软件检测

    恶意软件是指恶意软件犯罪者用来感染个人计算机或整个组织的网络的软件。 它利用目标系统漏洞&#xff0c;例如可以被劫持的合法软件&#xff08;例如浏览器或 Web 应用程序插件&#xff09;中的错误。 恶意软件渗透可能会造成灾难性的后果&#xff0c;包括数据被盗、勒索或网…...

    2024/5/8 1:37:31
  21. JS原型对象prototype

    让我简单的为大家介绍一下原型对象prototype吧&#xff01; 使用原型实现方法共享 1.构造函数通过原型分配的函数是所有对象所 共享的。 2.JavaScript 规定&#xff0c;每一个构造函数都有一个 prototype 属性&#xff0c;指向另一个对象&#xff0c;所以我们也称为原型对象…...

    2024/5/8 12:44:41
  22. C++中只能有一个实例的单例类

    C中只能有一个实例的单例类 前面讨论的 President 类很不错&#xff0c;但存在一个缺陷&#xff1a;无法禁止通过实例化多个对象来创建多名总统&#xff1a; President One, Two, Three; 由于复制构造函数是私有的&#xff0c;其中每个对象都是不可复制的&#xff0c;但您的目…...

    2024/5/8 9:51:44
  23. python django 小程序图书借阅源码

    开发工具&#xff1a; PyCharm&#xff0c;mysql5.7&#xff0c;微信开发者工具 技术说明&#xff1a; python django html 小程序 功能介绍&#xff1a; 用户端&#xff1a; 登录注册&#xff08;含授权登录&#xff09; 首页显示搜索图书&#xff0c;轮播图&#xff0…...

    2024/5/8 1:37:29
  24. 电子学会C/C++编程等级考试2022年03月(一级)真题解析

    C/C++等级考试(1~8级)全部真题・点这里 第1题:双精度浮点数的输入输出 输入一个双精度浮点数,保留8位小数,输出这个浮点数。 时间限制:1000 内存限制:65536输入 只有一行,一个双精度浮点数。输出 一行,保留8位小数的浮点数。样例输入 3.1415926535798932样例输出 3.1…...

    2024/5/7 17:09:45
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57