Java集合学习(带源码)
前言:为什么要使用Java集合容器
现在在我们写项目的时候Java集合类容器是最常用来存放对象或者数据的,在接触容器之前我们最常使用的就是数组,那么为什么不继续使用数组而要换成集合容器呢?
在使用数组时会存在几个不足:
- 数组的大小在创建的时候就必须声明,声明后不能更改。
- 数组只能存放同一类型的数据。
- 在数组中使用增删改查较为麻烦。
Java集合容器就解决这些问题
- 集合可以在大小不够时实现一定的扩容
- 集合可以保存任意对象
- 集合提供了一系列增删改查的方法,方便人们的使用
Java集合框架的开始
java最初的版本只为了最常用的数据结构提供了很少的一组类
Vector、Stack、Hashtable、BitSet与Enumeration接口
Enumeration接口提供了一种用于访问任意容器中的各个元素的抽象机制——《Java核心技术》
Enumeration接口源码
public interface Enumeration<E> {/*** Tests if this enumeration contains more elements.** @return <code>true</code> if and only if this enumeration object* contains at least one more element to provide;* <code>false</code> otherwise.*/boolean hasMoreElements(); //用来判断集合里是否还有元素,有则返回true,无则返回false/*** Returns the next element of this enumeration if this enumeration* object has at least one more element to provide.** @return the next element of this enumeration.* @exception NoSuchElementException if no more elements exist.*/E nextElement();// 返回集合的下一个元素,如果无元素返回则抛出:NoTouchElementException异常
}
在Java1.2后设计者推出了一组功能完善的数据结构类库—Java集合框架
可见Java集合容器的创建的就是为了推出了一组功能完善的数据结构类库用来给人们使用,存放数据。所以在理解集合容器中,数据结构是特别关健的一步。
集合接口和实现分离
和现代的数据结构结构类库常见做法一样,java集合类库也将接口与实现分离——《Java核心技术》
特点:只有在构造集合对象时,才会使用具体的类–可以使用接口类型来存放集合引用
@SuppressWarnings({"all"})public static void main(String[] args) {// 只有在构造集合对象时,才会使用具体的类--可以使用接口类型来存放集合引用List list = new ArrayList();// 使用时看不到具体的实现类list.add("learn");}
好处:一旦想使用其他的实现,只要改变构造集合对象时使用的集合引用就可以了
@SuppressWarnings({"all"})public static void main(String[] args) {// 只有在构造集合对象时,才会使用具体的类--可以使用接口类型来存放集合引用//List list = new ArrayList(); -> List list = new LinkedList(); 改变构造集合对象时使用的集合引用List list = new LinkedList();// 使用时看不到具体的实现类list.add("ArrayList");// 改变构造集合对象时使用的集合引用list.add("LinkedList");}
Java集合学习的正式开始
集合常见的接口及实现类(记住)
Collection接口
集合类的基本接口是collection接口(Map接口也是),且它是单列集合——(存放一个而不是一对元素)
两个基本方法
boolean add (E element) // 向集合添加元素。如果添加元素确实改变了集合就返回true;如果集合没有发生变化就返回false。Iterator<E> iterator();// 返回一个迭代器。可以使用这个迭代器依次访问集合中的元素
iterator接口(迭代器)
iterator接口包含4个方法
E next(); // 反复调用next方法,可以逐个访问集合中的每一个元素。如果到达了集合的末尾则抛出一个NoSuchElementException异常。因此在调用next方法前先调用hasNext方法判断是否还存在元素boolean hasNext();// hasNext方法判断是否还存在元素void remove();// 删除上次调用next方法时返回的元素default void forEachRemaining(Consumer<? super E?> action);// 可以实现这个方法来对每一个元素执行你提供的lambda表达式
从上面的描述中可以知道iterator接口中的方法
E next(); // 反复调用next方法,可以逐个访问集合中的每一个元素。如果到达了集合的末尾则抛出一个NoSuchElementException异常。因此在调用next方法前先调用hasNext方法判断是否还存在元素boolean hasNext();// hasNext方法判断是否还存在元素
和Enumeration接口中的方法
E nextElement();// 返回集合的下一个元素,如果无元素返回则抛出:NoTouchElementException异常boolean hasMoreElements(); //用来判断集合里是否还有元素,有则返回true,无则返回false
作用一样,但是Java集合框架的设计者不喜欢Enumeration接口里累赘的方法名所以引入了具有较短方法名的新接口iterator
遍历的方式
-
使用迭代器
-
使用增强for–foreach
使用foreach循环可以更加简练的表达同样的循环操作–编译器将其转成带有迭代器的循环
-
使用forEachRemaining方法
@SuppressWarnings({"all"})public static void main(String[] args) {Collection collection = new ArrayList();// 添加一个字符串boolean test = collection.add("LEARN");System.out.print(test+"\t");// 添加一个整形数据boolean test_ = collection.add(1);System.out.print(test_+"\t");// 添加一个对象boolean test_1 = collection.add(new Object());System.out.println(test_1+"\t");Iterator iterator = collection.iterator();// 遍历的方式// 第一种 使用迭代器System.out.println("第一种 使用迭代器");while (iterator.hasNext()) {Object next = iterator.next();System.out.println(next);}System.out.println("第二种 使用增强for--foreach");// 第二种 使用增强for--foreachfor (Object tmp : collection) {System.out.println(tmp);}// 第三种 使用forEachRemaining方法System.out.println("第三种 使用forEachRemaining方法");// 注意使用一次迭代器进行遍历后// 如果想重新遍历一次集合就要重新创建迭代器iterator = collection.iterator();iterator.forEachRemaining(tmp-> System.out.println(tmp));}
迭代器模型
Java集合类库中的迭代器与其他类库中的迭代器在概念上有很大的不同,在传统的集合库里,例如C++的标准模板库,迭代器是按数组索引建模的。如果给定这样一个迭代器,可以查找储存在指定位置上的元素,就像知道索引i就可以直接查找数组元素a[i]。不需要查找元素,也可以向前移动一个位置。这与不需要执行查找操作而通过i++将数组索引向前移动一样。但是Java迭代器并不是这样处理的。查找操作和位置变更紧密耦合。查找元素的唯一方法就是调用next方法,而在执行查找操作的同时,迭代器的位置就会随之向前移动。
因此可以认为Java迭代器位于两个元素之间。当调用next时,迭代器就越过下一个元素,并返回刚刚越过元素的引用 —《Java核心技术》
还可以把Iterator.next和InputStream.read看成等效的。InputStream.read读取一个字节就会消耗一个字节。下次调用就会消耗并返回输入的下一个字节。这和Iterator.next有异曲同工之妙。
再举一个例子
传统的集合库里的迭代器执行查找
就像外卖小哥送外买,小哥如果知道门牌号的话就可以直接找到顾客,不知道的话就只能一个一个的敲门了,如果他突然觉得有一个门不像点的起外卖的样子就可以不敲这个门而直接去下一个门口。
简单来说传统的集合库里的迭代器就是查找和位置变更关系不大
Java迭代器执行查找
就像闯关拿奖,你想拿到一个电冰箱,可是要闯过一关才可以知道并且得到这个奖品,并且只能闯完一关才可以前往下一关,那你只能一个一个的闯关,直到你拿到你想要的电冰箱
查找操作和位置变更紧密耦合。查找元素的唯一方法就是调用next方法,而在执行查找操作的同时,迭代器的位置就会随之向前移动。
List集合(列)
List集合是一个有序集合。元素会增加到指定位置。可以采用两种方式访问元素:使用迭代器进行访问,或者使用一个整数索引来访问。后面这种方法称之为随机访问,因为这样可以按任意顺序访问元素》与之不同,使用迭代器访问时,必须顺序的访问元素—《Java核心技术》
List集合的遍历
除了Collection接口的遍历方法,还可以使用普通的for循环进行遍历
public static void main(String[] args) {// 使用无参构造器List l = new ArrayList();for (int i = 0; i < 5; i++) {l.add("List" + i);}// 使用普通for循环进行遍历for (int i = 0; i < l.size(); i++) {System.out.println(l.get(i));}}
ArrayList集合
之前也说过集合框架的创建是为了提供一些数据结构类库给人们进行存放数据那么在ArrayList集合里则封装了一个动态再分配的对象数组。
来总结一下ArrayList的特点
- ArrayList底层维护了一个Object类型的数组
- ArrayList线程不安全(多线程不建议使用ArrayList)
- 如果选择无参构造器则,初始化数组大小为0(jdk7是10),第一次扩容为10,第二次则扩容为旧容量的1.5倍
- 如果选择有参构造器则,初始化数组大小为你提供的参数大小,之后扩容为旧容量的1.5倍
- ArrayList可以存放重复数据(可以加入null,并且不限定个数)
源码分析
@SuppressWarnings({"all"})public static void main(String[] args) {// 使用无参构造器List l = new ArrayList();for (int i = 0; i < 5; i++) {l.add("List" + i);}}
Vector类
Vector类也封装了一个对象数组
Vector类的特点
- Vector底层也封装了对象数组
- Vector线程安全(线程同步),Vector类的操作方法带有synchronized关键字
- Vector类使用无参构造器时默认数组大小为10,如果需要扩容则扩容为原来的两倍
- Vector类可以使用构造函数自定义数组初始大小和每次扩容大小
- 也可以存放重复数据(可以加入null,并且不限定个数)
我们也可以简单看一下它的源码
public static void main(String[] args) {List list = new Vector();list.add("test");}
LinkList集合
LinkList的特点
- LinkList类底层封装的是一个双向链表。
- LinkList集合线程未同步(线程不安全)。
- LinkList也可以存放重复数据(可以加入null,并且不限定个数)。
@SuppressWarnings({"all"})public static void main(String[] args) {List list = new LinkedList();list.add("List");list.add("List");}
下面我来简单介绍一下具体的添加方法
总结一下List集合
List集合其实并不是特别难,底层使用的数据结构也不是特别困难,但是也有几个要点要记住
-
List集合的多种遍历方法
a. 使用迭代器
b.使用foreach循环
c. 使用普通for循环
d.使用forEachRemaining方法
-
List集合各个具体实现的扩容方法(重点)
ArrayList集合具体扩容方法
private void grow(int minCapacity) {// minCapacity 如果使用无参构造函数第一次扩容则为10// overflow-conscious codeint oldCapacity = elementData.length;int newCapacity = oldCapacity + (oldCapacity >> 1); // oldCapacity + (oldCapacity >> 1) -> 1.5*oldCapacityif (newCapacity - minCapacity < 0) // 如果扩容还是不够就扩容到minCapacity大小newCapacity = minCapacity;if (newCapacity - MAX_ARRAY_SIZE > 0)// 如果大于MAX_ARRAY_SIZE(Integer.MAX_VALUE - 8)则扩容到Integer.MAX_VALUEnewCapacity = hugeCapacity(minCapacity);// minCapacity is usually close to size, so this is a win:elementData = Arrays.copyOf(elementData, newCapacity);}
Vector集合具体扩容方法
private void grow(int minCapacity) {// minCapacity 如果使用无参构造函数第一次扩容则为10// overflow-conscious codeint oldCapacity = elementData.length;int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);// capacityIncrement为自定义扩容大小,如果不定义则为0,并使用默认扩容大小(扩容为原来的两倍)if (newCapacity - minCapacity < 0) // 如果扩容还是不够就扩容到minCapacity大小newCapacity = minCapacity;if (newCapacity - MAX_ARRAY_SIZE > 0)// 如果大于MAX_ARRAY_SIZE(Integer.MAX_VALUE - 8)则扩容到Integer.MAX_VALUEnewCapacity = hugeCapacity(minCapacity);elementData = Arrays.copyOf(elementData, newCapacity);}
LinkList集合具体扩容方法
// 使用尾插法把新接点插入尾部,具体步骤可以看介绍LinkList时的图 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++; }
-
在什么情况下选择什么类型的具体实现类
在需要线程安全的情况下
建议使用Vector集合,因为它的所有方法都是同步的,都使用synchronized 关键字 加了一个显式锁
在不需要保证线程安全的情况下,又要进行改查的操作比较多
建议使用ArrayList集合,因为它底层是一个数组方便进行查询
在不需要保证线程安全的情况下,又要进行增删的操作比较多
建议使用LinkList集合,因为它底层是一个双向链表方便进行增加和删除节点
Set集合(集)
从现在开始,集合的难度提升了一截因为,Set集合的具体实现类所封装的数据结构要复杂一点。
Set接口等同于Collection接口,不过其方法的行为有更加严谨的定义。集的add方法不允许增加重复的元素。要适当的定义集的equals方法:只有两个集包含同样的元素就认为他们是相等的,而不要求这些元素有同样的顺序。hashCode方法的定义要保证包含相同的元素的集会得到相同的散列码–《Java核心技术》
Set集合不能使用普通for进行遍历,因为他是无序的。
Hashset集合
HashSet的特点
- HashSet底层封装的是一个散列表(数组+链表+红黑树)
- HashSet不能存放相同的元素,可以添加一个null
- HashSet存放元素的顺序和取出对象的顺序不一样
- HashSet取出对象的顺序固定
- HashSet实际上是一个HashMap,存放的元素作为k值,使用一个对象统一作为v值
散列表模型
源码分析
@SuppressWarnings({"all"})
public static void main(String[] args) {Set set = new HashSet();set.add("HashSet");set.add(new Object());
}
由于putVal方法十分复杂所以特别把它提出来讲
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {Node<K,V>[] tab;ß Node<K,V> p; int n, i;if ((tab = table) == null || (n = tab.length) == 0) // table数组在第一次使用时也就是刚刚初始化后为null,进行第一次扩容数组,table为存放记录的数组n = (tab = resize()).length; // resize为扩容函数if ((p = tab[i = (n - 1) & hash]) == null) // 计算出存放位置的索引,i = (n - 1) & hash 相当于 hash %(i=(n-1)) ,如果为空就意味着未被填充直接把元素放到该位置上的数组里tab[i] = newNode(hash, key, value, null);else {// 如果不为空就意味着该位置已经被填充Node<K,V> e; K k;// 把该位置上的元素和需要放入数组的元素进行比较,如果相同就使用局部变量e来存放该位置节点上的元素if (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))e = p;// 如果和该位置是的元素不相同,并且已经扩容为红黑树else if (p instanceof TreeNode)// 则按存放元素到树的方法执行存放存放e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);else {// 如果和该位置是的元素不相同,并且还未扩容为红黑树,执行下面循环for (int binCount = 0; ; ++binCount) {// 如果移到链表末尾也没发现一样的,就插入元素到末尾(1.7之前是使用头插法,1.8后使用尾插法)if ((e = p.next) == null) {p.next = newNode(hash, key, value, null);if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1sttreeifyBin(tab, hash);break;}// 如果相等的话直接退出,此时e为与传入元素相等的元素 if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))break;p = e;}}// 如果e不为空说明存在重复元素,进行值的替换,返回替换的值if (e != null) { // existing mapping for keyV oldValue = e.value;if (!onlyIfAbsent || oldValue == null)e.value = value;afterNodeAccess(e);return oldValue;}}// 修改一次后加一++modCount;// 如果存放在集合里的元素大于存放元素阀值(为当前最大存放数*装填因子(默认为0.75)),进行扩容if (++size > threshold)resize();afterNodeInsertion(evict);return null;
}
resize为扩容函数
final Node<K,V>[] resize() {Node<K,V>[] oldTab = table; // 使用临时变量oldTab存放原来的数组地址int oldCap = (oldTab == null) ? 0 : oldTab.length; // oldCap如果为null,则为0,负责则为原来的数组长度int oldThr = threshold;// oldThr存放原来的储存阀值int newCap, newThr = 0;if (oldCap > 0) { // 如果原来的oldCap大于0if (oldCap >= MAXIMUM_CAPACITY) { // 如果原来的oldCap大于MAXIMUM_CAPACITY (1 << 30)threshold = Integer.MAX_VALUE; // 使储存阀值为 MAX_VALUE (0x7fffffff)return oldTab; // 返回旧数组地址}// 如果原来的oldCap 乘 2小于 MAXIMUM_CAPACITY 并且 原来的oldCap大于等于DEFAULT_INITIAL_CAPACITY (16) else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY && oldCap >= DEFAULT_INITIAL_CAPACITY)// 使新阀值为旧阀值的两倍newThr = oldThr << 1; // double threshold}// 如果oldCap = 0 ,且 oldThr > 0,说明自定义了阀值 ,则把初始容量设置为阈值else if (oldThr > 0) // initial capacity was placed in thresholdnewCap = oldThr;// 如果使用无参构造器后,第一次扩容就 把数组大小扩容为 16 ,阀值设置为 16*0.75 = 12else { // zero initial threshold signifies using defaultsnewCap = DEFAULT_INITIAL_CAPACITY;newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);}if (newThr == 0) {float ft = (float)newCap * loadFactor;newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?(int)ft : Integer.MAX_VALUE);}threshold = newThr;@SuppressWarnings({"rawtypes","unchecked"})// 扩容后,按扩容后大小定义一个newTab并且把其地址交给tableNode<K,V>[] newTab = (Node<K,V>[])new Node[newCap];table = newTab;// 把元素重新插入表中if (oldTab != null) {for (int j = 0; j < oldCap; ++j) {Node<K,V> e;if ((e = oldTab[j]) != null) {oldTab[j] = null;if (e.next == null)newTab[e.hash & (newCap - 1)] = e;else if (e instanceof TreeNode)((TreeNode<K,V>)e).split(this, newTab, j, oldCap);else { // preserve orderNode<K,V> loHead = null, loTail = null;Node<K,V> hiHead = null, hiTail = null;Node<K,V> next;do {next = e.next;if ((e.hash & oldCap) == 0) {if (loTail == null)loHead = e;elseloTail.next = e;loTail = e;}else {if (hiTail == null)hiHead = e;elsehiTail.next = e;hiTail = e;}} while ((e = next) != null);if (loTail != null) {loTail.next = null;newTab[j] = loHead;}if (hiTail != null) {hiTail.next = null;newTab[j + oldCap] = hiHead;}}}}}// 符合新建数组地址return newTab;
}
LinkHashSet集合
LinkHashSet集合的特点
-
LinkHashSet是HashSet的子类
-
LinkHashSet与HashSet的不同就是,他在原来散列表的基础上做了一点改变(数组+双向链表)
-
LinkHashSet通过HashCode值来确定保存元素位置,但是由于增加了一个双向链表,所以维护了数组的插入顺序
-
LinkHashSet是有序的
-
LinkHashSet不允许存放重复元素
-
LinkHashSet底层是LinkHashMap
数据结构模型
源码分析
public class LinkHashSet_ {@SuppressWarnings({"all"})public static void main(String[] args) {Set set = new LinkedHashSet();set.add("LHS");}
}
LinkHashSet集合的增加方法和HashSet的增加方法基本一致只是重载了一些方法
例如
if ((p = tab[i = (n - 1) & hash]) == null) // 计算出存放位置的索引,i = (n - 1) & hash 相当于 hash %(i=(n-1)) ,如果为空就意味着未被填充直接把元素放到该位置上的数组里/*****/tab[i] = newNode(hash, key, value, null);/*****/
/**************************************************************************************/for (int binCount = 0; ; ++binCount) {// 如果移到链表末尾也没发现一样的,就插入元素到末尾(1.7之前是使用头插法,1.8后使用尾插法)if ((e = p.next) == null) {/*****/p.next = newNode(hash, key, value, null);/*****/if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1sttreeifyBin(tab, hash);break;}// 如果相等的话直接退出,此时e为与传入元素相等的元素 if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))break;p = e;}
Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) { // newNode返回的是一个LinkedHashMap.Entry对象LinkedHashMap.Entry<K,V> p =new LinkedHashMap.Entry<K,V>(hash, key, value, e);linkNodeLast(p); // 执行插入数据return p;
}
TreeSet集合(树集)
TreeSet集合的特点
- TreeSet的集合是一个有序集合,可以以任意顺序插入到集合里去
- TreeSet集合如果使用无参构造器,则按默认升序排序
- TreeSet底层使用的是一个红黑树
- TreeSet集合提供了一个构造器,可以传入一个比较器,来指定一个排序方法
Set set = new TreeSet(new Comparator() {// 指定比较方法 // 如((String)o1).compareTo((String) o2) 比较字符串大小@Overridepublic int compare(Object o1, Object o2) {return ((String)o1).compareTo((String) o2);}});
- TreeSet底层是TreeMap
源码分析
@SuppressWarnings({"all"})
public static void main(String[] args) {// Set set = new TreeSet();Set set = new TreeSet(new Comparator() {// 指定比较方法// 如((String)o1).compareTo((String) o2) 比较字符串大小@Overridepublic int compare(Object o1, Object o2) {return ((String)o1).compareTo((String) o2);}});set.add("cdfde");set.add("cdfd");set.add("cdf");set.add("cd");}
put方法源码分析
public V put(K key, V value) {Entry<K,V> t = root;if (t == null) { // 第一次添加compare(key, key); // type (and possibly null) check 检查类型是否为nullroot = new Entry<>(key, value, null);size = 1;modCount++;return null;}int cmp;Entry<K,V> parent;// split comparator and comparable pathsComparator<? super K> cpr = comparator; // 把我们传入比较器给 cprif (cpr != null) {do {parent = t; // 使用比较器比较值cmp = cpr.compare(key, t.key);if (cmp < 0) t = t.left;else if (cmp > 0)t = t.right;else// 等于0则说明key值(或者对应的key类型)已经存在,则修改key对应的value(TreeSet里则为不存入key值)return t.setValue(value);} while (t != null);}else {if (key == null)throw new NullPointerException();@SuppressWarnings("unchecked")Comparable<? super K> k = (Comparable<? super K>) key;do {parent = t;cmp = k.compareTo(t.key);if (cmp < 0)t = t.left;else if (cmp > 0)t = t.right;elsereturn t.setValue(value);} while (t != null);}Entry<K,V> e = new Entry<>(key, value, parent);if (cmp < 0)parent.left = e;elseparent.right = e;fixAfterInsertion(e);size++;modCount++;return null;
}
总结一下Set集合
- Set集合的遍历方式
a.使用迭代器遍历
b.使用增强for遍历
**c.使用forEachRemaining方法 **
@SuppressWarnings({"all"})
public static void main(String[] args) {Set set = new HashSet();set.add("HashSet");set.add(new Object());set.add("a");set.add("bd");Iterator iterator = set.iterator();while (iterator.hasNext()) {Object next = iterator.next();System.out.println(next);}System.out.println("=========================");for (Object next:set) {System.out.println(next);}System.out.println("=========================");Iterator iterator = set.iterator();iterator.forEachRemaining(next ->System.out.println(next));}
-
HashSet的扩容方法
为了尽量少的避免哈希碰撞,设置了装载因子(默认为0.75),第一次扩容数组为16,装载阀值为 16 * 0.75 = 12, 所以当存放元素总数到达阀值时,数组扩容为两倍且进行再散列,如果数组的一个位置链表大小为8且数组大小为64,则进行树化该链表来存放元素。
-
HashSet和LinkHashSet以及TreeSet的区别
HashSet是无序的,它存放元素是按照计算他们的散列码来存放
LinkHashSet在HashSet的基础上使用了双向链表,来维持元素的插入顺序,看起来像是按顺序插入的
TreeSet是一个有序集合,它可以按照比较器来存放相关的元素
-
Set集合和Map有千丝万缕的关系
HashSet和LinkHashSet以及TreeSet的底层都是对应Map的具体集合实现类
Map集合(映射)
和collection接口一样,map接口也是集合的基本接口,但是map是双列集合,说明存放的元素为 k-y 形式,之前的Set集合(集),可以让你快速的查找现有的元素,但是需要你提供一个和所寻找的元素相同的副本,这无疑是不现实的事。在更多的情况下我们需要的是可以提供一个关键信息来寻找对应的元素,就像查字典通过首字母来查找对应的页数。
Map 集合常用集合实现类
HashMap集合
HashMap集合的特点
- HashMap的底层维护的是一个散列表
- 创建对象会把装载因子初始化为0.75
- 第一次扩容为16,之后扩容为原来的两倍
- Map集合不能重复key值
- Map 集合可以重复value值
之前也说过HashSet集合的底层其实就是HashMap所以,HashMap集合底层的数据结构和源码分析和HashSet是大径相同的。
public static void main(String[] args) {Map map = new HashMap();map.put("key","vaule");
}
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {Node<K,V>[] tab;ß Node<K,V> p; int n, i;if ((tab = table) == null || (n = tab.length) == 0) // table数组在第一次使用时也就是刚刚初始化后为null,进行第一次扩容数组,table为存放记录的数组n = (tab = resize()).length; // resize为扩容函数if ((p = tab[i = (n - 1) & hash]) == null) // 计算出存放位置的索引,i = (n - 1) & hash 相当于 hash %(i=(n-1)) ,如果为空就意味着未被填充直接把元素放到该位置上的数组里tab[i] = newNode(hash, key, value, null);else {// 如果不为空就意味着该位置已经被填充Node<K,V> e; K k;// 把该位置上的元素和需要放入数组的元素进行比较,如果相同就使用局部变量e来存放该位置节点上的元素if (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))e = p;// 如果和该位置是的元素不相同,并且已经扩容为红黑树else if (p instanceof TreeNode)// 则按存放元素到树的方法执行存放存放e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);else {// 如果和该位置是的元素不相同,并且还未扩容为红黑树,执行下面循环for (int binCount = 0; ; ++binCount) {// 如果移到链表末尾也没发现一样的,就插入元素到末尾(1.7之前是使用头插法,1.8后使用尾插法)if ((e = p.next) == null) {p.next = newNode(hash, key, value, null);if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1sttreeifyBin(tab, hash);break;}// 如果相等的话直接退出,此时e为与传入元素相等的元素 if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))break;p = e;}}// 如果e不为空说明存在重复元素,进行值的替换,返回替换的值if (e != null) { // existing mapping for keyV oldValue = e.value;if (!onlyIfAbsent || oldValue == null)e.value = value;afterNodeAccess(e);return oldValue;}}// 修改一次后加一++modCount;// 如果存放在集合里的元素大于存放元素阀值(为当前最大存放数*装填因子(默认为0.75)),进行扩容if (++size > threshold)resize();afterNodeInsertion(evict);return null;
}
LinkHashMap集合
LinkHashMap特点
-
是HashMap的子集
-
在散列表的基础上使用了双向链表维护了插入顺序
-
维护了数组的插入顺序
-
不允许存放key值相同的元素
源码分析
public static void main(String[] args) {Map map = new LinkedHashMap();map.put("key","value");
}
TreeMap集合
TreeMap集合特点
- 是一个有序集合,可以以任意顺序插入到集合里去
- 如果使用无参构造器,则按默认升序排序
- 使用的是一个红黑树(平衡二叉树)
- 提供了一个构造器,可以传入一个比较器,来指定一个排序方法
源码分析
public static void main(String[] args) {Map map = new TreeMap();map.put("cd","123");
}
public V put(K key, V value) {Entry<K,V> t = root;if (t == null) { // 第一次添加compare(key, key); // type (and possibly null) check 检查类型是否为nullroot = new Entry<>(key, value, null);size = 1;modCount++;return null;}int cmp;Entry<K,V> parent;// split comparator and comparable pathsComparator<? super K> cpr = comparator; // 把我们传入比较器给 cprif (cpr != null) {do {parent = t; // 使用比较器比较值cmp = cpr.compare(key, t.key);if (cmp < 0) t = t.left;else if (cmp > 0)t = t.right;else// 等于0则说明key值(或者对应的key类型)已经存在,则修改key对应的value(TreeSet里则为不存入key值)return t.setValue(value);} while (t != null);}else {if (key == null)throw new NullPointerException();@SuppressWarnings("unchecked")Comparable<? super K> k = (Comparable<? super K>) key;do {parent = t;cmp = k.compareTo(t.key);if (cmp < 0)t = t.left;else if (cmp > 0)t = t.right;elsereturn t.setValue(value);} while (t != null);}Entry<K,V> e = new Entry<>(key, value, parent);if (cmp < 0)parent.left = e;elseparent.right = e;fixAfterInsertion(e);size++;modCount++;return null;
}
HashTable集合
HashTable集合特点
-
存放的元素是键值对
-
hashtable的建和值都不可以为null
-
它是线程安全的
-
HashTable底层是一个Entry[]数组,使用无参构造器时默认大小为11,装载因子为0.75。
-
按照 原来大小乘二加一扩容
源码分析
public static void main(String[] args) {Map map = new Hashtable();map.put("key",123);
}
public Hashtable(int initialCapacity, float loadFactor) {// initialCapacity 初始数组大小, loadFactor 装载因子if (initialCapacity < 0) // 如果数组大小为负数 抛出异常throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);if (loadFactor <= 0 || Float.isNaN(loadFactor)) // 如果loadFactor 装载因子为非正数或者为非数抛出异常throw new IllegalArgumentException("Illegal Load: "+loadFactor);if (initialCapacity==0)// 如果数组大小为0则使其等于一initialCapacity = 1;this.loadFactor = loadFactor;table = new Entry<?,?>[initialCapacity]; // 创建数组threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1); // 设置装载阀值
}
public synchronized V put(K key, V value) { // synchronized关键字,保证方法同步// Make sure the value is not nullif (value == null) { // value为空则抛出空指针异常throw new NullPointerException();}// Makes sure the key is not already in the hashtable.Entry<?,?> tab[] = table;int hash = key.hashCode();int index = (hash & 0x7FFFFFFF) % tab.length; // 计算散列码来作为索引@SuppressWarnings("unchecked")Entry<K,V> entry = (Entry<K,V>)tab[index];for(; entry != null ; entry = entry.next) { if ((entry.hash == hash) && entry.key.equals(key)) { // 查看是否有重复的元素V old = entry.value; // 有则替换value值entry.value = value;return old;// 返回旧value值}}addEntry(hash, key, value, index); // 执行添加元素方法return null;
}
private void addEntry(int hash, K key, V value, int index) {modCount++; // 集合修改次数加一Entry<?,?> tab[] = table;if (count >= threshold) { // 存在集合元素数大于阀值// Rehash the table if the threshold is exceededrehash(); // 扩容tab = table;hash = key.hashCode();index = (hash & 0x7FFFFFFF) % tab.length;}// Creates the new entry.@SuppressWarnings("unchecked")Entry<K,V> e = (Entry<K,V>) tab[index];tab[index] = new Entry<>(hash, key, value, e); // 添加元素count++; // 集合元素数加一
}
protected void rehash() { // 扩容集合方法int oldCapacity = table.length;Entry<?,?>[] oldMap = table;// overflow-conscious codeint newCapacity = (oldCapacity << 1) + 1; // 扩容为原来的两倍加一if (newCapacity - MAX_ARRAY_SIZE > 0) {if (oldCapacity == MAX_ARRAY_SIZE)// Keep running with MAX_ARRAY_SIZE bucketsreturn;newCapacity = MAX_ARRAY_SIZE;}Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];modCount++;threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);table = newMap;for (int i = oldCapacity ; i-- > 0 ;) {// 再散列,重新存放元素for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) {Entry<K,V> e = old;old = old.next;int index = (e.hash & 0x7FFFFFFF) % newCapacity;e.next = (Entry<K,V>)newMap[index];newMap[index] = e;}}
}
Map集合总结
- Map集合是双列集合 (存放元素为key-value)
- Map集合中Key值不可以重复,Value值可以重复
- Map集合中存在一对一关系(Key对应一个Value)
- Map集合的遍历方式【**************】
Map集合的遍历方式(重点)
@SuppressWarnings({"all"})
public static void main(String[] args) {Map map = new HashMap();map.put("key","value");map.put("key","123");map.put("key","aaaa");// 第一类方法 通过使用Key集合来取出对应的value值Set set = map.keySet();// 因为使用的是Set集合所以Set集合的遍历方法都可以使用来取出key值// 迭代器Iterator iterator = set.iterator();while (iterator.hasNext()) {Object next = iterator.next();System.out.println(map.get(next));}// foreachfor (Object o :set) {System.out.println(map.get(o));}// 第二类方法 通过value集合来遍历Collection values = map.values();// Collection 接口的遍历方法都可以使用// 迭代器 \ foreach// 第三类 通过EntrySet 来获取 (重点)Set entrySet = map.entrySet();// 迭代器Iterator entrySetIterator = entrySet.iterator();while (entrySetIterator.hasNext()) {Map.Entry next = (Map.Entry) entrySetIterator.next();System.out.println(next.getKey()+"-"+next.getValue());}// for eachfor (Object o :entrySet) {Map.Entry tmp = (Map.Entry) o;System.out.println(tmp.getKey()+"-"+tmp.getValue());}}
后言
Java集合十分重要,我在这里也只是介绍了大概,还是需要好好的学习,在此推荐《Java核心技术》这本书,和B站韩顺平老师的Java合集视频https://www.bilibili.com/video/BV1YA411T76k,看完后相信会对你有一定的提高。我在看完后感觉受益匪浅。为了方便以后的复习所以整理了这些内容。如果有不足的地方,希望各位能够斧正。
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
相关文章
- 面试题集锦(非常适合初中级测试工程师)
题目整理 1.怎么判断元素是否存在? 2.如何判断元素是否出现? 3.selenium中hidden或者是display=none的元素是否可以定位到? 4.selenium中如何保证操作元素的成功率?也就是说如何保证我点击的元素一定是可以点击的&…...
2024/5/2 12:56:40 - 27 信息过滤与反垃圾,java语言程序设计教程课后题答案
我国的信息过滤技术是走在世界前列的,尽管如此,在各种社区网站和个人邮箱中, 广告和垃圾信息仍然屡见不鲜、泛滥成灾。 常用的信息过滤与反垃圾手段有以下几种。 1 文本匹配 文本匹配主要解决敏感词过滤的问题。通常网站维护一份敏感词列表,…...
2024/4/15 13:08:37 - Java完全自学手册,一册在手,offer我有(附程序员书单)
领取福利 15张学习路线导图3G学习资料10G计算机书籍 哈喽,大家好,我是一条~ Java学习如逆水行舟,不进则退。一条一路自学过来,踩过很多坑,吃过很多苦。 现在回想起来,当初要是能有一个完整的学习路线让我…...
2024/4/24 19:47:09 - 25 岁,毕业写前端的这三年,多益网络java面试
你当然可以指责那时的我只醉心技术而不管业务(这确实是某家大厂对我的面试评价),不过折腾起这些有趣的项目,让我感觉那时的生活比起在每个周末都要痛苦地赶(抄)作业的大学要自在得多。从旁观者的角度来看&a…...
2024/4/15 13:08:22 - 【缅怀钱老】学习实现火箭发射效果
前言 昨天是钱学森钱老逝世十二周年的日子,钱学森老先生对我国两弹一星事业的贡献是巨大的,借本文献上阿包无限的敬仰之情。 五年归国路,十年两弹成。 每次提起钱老先生,我脑海中都会浮现出钱老先生面对陈赓将军询问我国可不可…...
2024/5/7 17:14:35 - CloudCompare 二次开发注意事项
一、修改生成exe图标及exe文件名 1、在CloudCompare\qCC\images\icon源码目录添加wx_icon.ico和wx_icon.rc文件,修改rc文件内容,变为自己的图标名 2、修改qCC目录CMakeLists.txt文件,prject为工程名,rc_list修改为wx_icon.ico 3…...
2024/5/8 11:33:22 - php毕业设计课题选题作品之php新闻管理系统(1)开题报告
...
2024/4/15 13:08:27 - Python requests发送multipart/form-data请求
依赖第三方包 from requests_toolbelt import MultipartEncoder import requests from requests_toolbelt import MultipartEncoderm MultipartEncoder(fieldsquer_m, # quer_m是post请求需要的参数boundary------.join(random.sample(string.ascii_letters string.digit…...
2024/4/15 13:08:12 - GIt版本管理,基础
常用命令 git status 对比状态git log 查看提交日志 git log --oneline 简化git branch 分支名 建立本地新分支git checkout 分支名 切换本地分支git branch -d 分支名 删除分支删除未合并的分支:git branch -D 分支名在pull以后的主分支上git merge feature &…...
2024/5/3 22:31:07 - 浏览器三种存储方式之间的区别
参考链接: 浏览器三种存储方式之间的区别 为什么要进行数据存储 随着Web应用程序的出现,慢慢的也开始产生了对于能够直接在客户端上存储用户信息能力的要求,我们知道当我们访问某个页面的时候,很多东西都需要从服务器端进行加载…...
2024/4/19 12:51:15 - 佳莱科技董事长熊银河:身体是住的地方
近日,佳莱科技董事长熊银河给佳莱人分享了一堂课,叫做《健康一生》。在该课程中,他对“健康”和“养生”进行了全新的解读,不禁使现场的佳人们受益良多,甚至是醍醐灌顶。那么,现在就让我们一起来看看这堂课…...
2024/5/7 12:50:23 - 微信小程序个人中心页面开发
概述 写一个非常简单的个人中心页面,包括一下内容 登录区域,根据是否登录显示不同的内容文字显示区域,只是显示文本文字显示区域绑定事件,可以拨打电话 一些技术总结包括 条件渲染的使用wx:if等,官方链接https://d…...
2024/5/4 7:46:04 - 2021爆火的GitHub上标星75k+“Java面试突击宝典
2.3 Jave多线程 2.4 Java虚拟机 2.5 设计模式 三、计算机网络常见面试点总结 3.1 TCP、UDP协议的区别 3.2 在浏览器中输入ur1地址->>显示主页的过程 3.3 各种协议与HTTP协议之间的关系 3.4 HTTP长连接、短连接 3.5 TCP三次握手和四次挥手面试常客) 四、Linux 4.1…...
2024/4/17 23:02:49 - Flume
文章目录flume基本架构AgentSourceSinkChannelEventSpoolingDirSource(监控一个目录)TailDirSource(监控多个文件目录中的多个文本文件)事务flume基本架构 Flume 是 Cloudera 提供的一个高可用的,高可靠的,…...
2024/5/8 5:54:46 - 常见病毒查杀与防御技巧(from:http://www.ccoo.cn/blog/blogshow.asp?aid=184498)
有人认为杀毒是一件简单的事情,不就是点击杀毒软件的“杀毒”按钮就行了吗? 不错,杀毒的确要借助杀毒软件,但是不是说一点击杀毒就万事大吉的。这就是为什么有的人一次性就将病毒杀尽,有的人机子内的病毒永远也杀不完的原因了。杀毒也要讲技巧!对于杀毒的设置本文就不做介…...
2024/5/2 21:48:42 - 欧拉习题17
题目如下: If the numbers 1 to 5 are written out in words: one, two, three, four, five, then there are 3 3 5 4 4 19 letters used in total. If all the numbers from 1 to 1000 (one thousand) inclusive were written out in words, how many letters…...
2024/5/7 2:53:43 - JAVA学习——008.流程控制——循环结构
for循环语句: 格式: for(初始化语句;条件判断语句;条件控制语句){ 循环体语句; } 执行流程: 初始化条件语句——>条件判断语句——>(true)循环体语句…...
2024/4/15 13:09:22 - 【leetcode】日积月累,每日一题--203. 移除链表元素(DayDayUp 12)
前言:\textcolor{Green}{前言:}前言:今天开始一下链表的题目训练,前面数组的训练还得进行,可以双面一起来。 移除链表元素一、题目二、代码及思路题目来源 等级:简单\textcolor{OrangeRed}{等级:…...
2024/4/20 5:04:26 - (C语言之路-----p1:分支和循环)
在现实中,事情发展的顺序可以概括成三种 在c语言中程序的运行顺序也是如此划分为几种,一种是从上至下运行,一种是分支结构,另一种是循环结构,c语言比现实生活中多出的一种是跳转(goto语句) 接下来,我们将介…...
2024/4/30 6:37:42 - Facebook封号有哪些应对措施?
Facebook封号的问题已经成为了电商们的固定话题,现在社交媒体账号针对广告账户的审核越来越严格,封号后应该如何进行应对呢? Facebook禁止广告账户的原因 奇怪的操作 使用的支付账户与注册人的姓名不符;使用其他国家发行的卡片&a…...
2024/4/15 13:09:17
最新文章
- YOLO系列自研改进:基于注意力机制的多尺度特征提取模块
目录 一、原理 二、代码 三、在YOLO中的应用 一、原理 这个模块的原理仍然是利用不同大小的卷积核来提取不同尺度的特征,同样将通道划分为两部分,一部分通过注意力机制进行通道信息和空间信息的提取,另一部分通过多个不同大小的卷积核来提取多尺度的特征信息。 二、代码…...
2024/5/8 11:34:45 - 梯度消失和梯度爆炸的一些处理方法
在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言,在此感激不尽。 权重和梯度的更新公式如下: w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...
2024/5/7 10:36:02 - 五一假期来临,各地景区云旅游、慢直播方案设计与平台搭建
一、行业背景 经文化和旅游部数据中心测算,今年清明节假期3天全国国内旅游出游1.19亿人次,按可比口径较2019年同期增长11.5%;国内游客出游花费539.5亿元,较2019年同期增长12.7%。踏青赏花和户外徒步成为假期的热门出游主题。随着…...
2024/4/30 7:54:16 - 第十二届蓝桥杯省赛真题(C/C++大学B组)
目录 #A 空间 #B 卡片 #C 直线 #D 货物摆放 #E 路径 #F 时间显示 #G 砝码称重 #H 杨辉三角形 #I 双向排序 #J 括号序列 #A 空间 #include <bits/stdc.h> using namespace std;int main() {cout<<256 * 1024 * 1024 / 4<<endl;return 0; } #B 卡片…...
2024/5/7 4:57:38 - 开启 Keep-Alive 可能会导致http 请求偶发失败
大家好,我是蓝胖子,说起提高http的传输效率,很多人会开启http的Keep-Alive选项,这会http请求能够复用tcp连接,节省了握手的开销。但开启Keep-Alive真的没有问题吗?我们来细细分析下。 最大空闲时间造成请求…...
2024/5/5 19:08:29 - 【外汇早评】美通胀数据走低,美元调整
原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...
2024/5/8 6:01:22 - 【原油贵金属周评】原油多头拥挤,价格调整
原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...
2024/5/7 9:45:25 - 【外汇周评】靓丽非农不及疲软通胀影响
原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...
2024/5/4 23:54:56 - 【原油贵金属早评】库存继续增加,油价收跌
原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...
2024/5/7 14:25:14 - 【外汇早评】日本央行会议纪要不改日元强势
原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...
2024/5/4 23:54:56 - 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响
原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...
2024/5/4 23:55:05 - 【外汇早评】美欲与伊朗重谈协议
原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...
2024/5/4 23:54:56 - 【原油贵金属早评】波动率飙升,市场情绪动荡
原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...
2024/5/7 11:36:39 - 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试
原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...
2024/5/4 23:54:56 - 【原油贵金属早评】市场情绪继续恶化,黄金上破
原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...
2024/5/6 1:40:42 - 【外汇早评】美伊僵持,风险情绪继续升温
原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...
2024/5/4 23:54:56 - 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势
原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...
2024/5/4 23:55:17 - 氧生福地 玩美北湖(上)——为时光守候两千年
原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...
2024/5/7 9:26:26 - 氧生福地 玩美北湖(中)——永春梯田里的美与鲜
原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...
2024/5/4 23:54:56 - 氧生福地 玩美北湖(下)——奔跑吧骚年!
原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...
2024/5/4 23:55:06 - 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!
原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...
2024/5/5 8:13:33 - 「发现」铁皮石斛仙草之神奇功效用于医用面膜
原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...
2024/5/4 23:55:16 - 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者
原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...
2024/5/4 23:54:58 - 广州械字号面膜生产厂家OEM/ODM4项须知!
原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...
2024/5/6 21:42:42 - 械字号医用眼膜缓解用眼过度到底有无作用?
原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...
2024/5/4 23:54:56 - 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...
解析如下:1、长按电脑电源键直至关机,然后再按一次电源健重启电脑,按F8健进入安全模式2、安全模式下进入Windows系统桌面后,按住“winR”打开运行窗口,输入“services.msc”打开服务设置3、在服务界面,选中…...
2022/11/19 21:17:18 - 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。
%读入6幅图像(每一幅图像的大小是564*564) 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 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...
win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面,在等待界面中我们需要等待操作结束才能关机,虽然这比较麻烦,但是对系统进行配置和升级…...
2022/11/19 21:17:15 - 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...
有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows,请勿关闭计算机”的提示,要过很久才能进入系统,有的用户甚至几个小时也无法进入,下面就教大家这个问题的解决方法。第一种方法:我们首先在左下角的“开始…...
2022/11/19 21:17:14 - win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...
置信有很多用户都跟小编一样遇到过这样的问题,电脑时发现开机屏幕显现“正在配置Windows Update,请勿关机”(如下图所示),而且还需求等大约5分钟才干进入系统。这是怎样回事呢?一切都是正常操作的,为什么开时机呈现“正…...
2022/11/19 21:17:13 - 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...
Win7系统开机启动时总是出现“配置Windows请勿关机”的提示,没过几秒后电脑自动重启,每次开机都这样无法进入系统,此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一:开机按下F8,在出现的Windows高级启动选…...
2022/11/19 21:17:12 - 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...
有不少windows10系统用户反映说碰到这样一个情况,就是电脑提示正在准备windows请勿关闭计算机,碰到这样的问题该怎么解决呢,现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法:1、2、依次…...
2022/11/19 21:17:11 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...
今天和大家分享一下win7系统重装了Win7旗舰版系统后,每次关机的时候桌面上都会显示一个“配置Windows Update的界面,提示请勿关闭计算机”,每次停留好几分钟才能正常关机,导致什么情况引起的呢?出现配置Windows Update…...
2022/11/19 21:17:10 - 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...
只能是等着,别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚,只能是考虑备份数据后重装系统了。解决来方案一:管理员运行cmd:net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...
2022/11/19 21:17:09 - 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?
原标题:电脑提示“配置Windows Update请勿关闭计算机”怎么办?win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢?一般的方…...
2022/11/19 21:17:08 - 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...
关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!关机提示 windows7 正在配…...
2022/11/19 21:17:05 - 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...
钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...
2022/11/19 21:17:05 - 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...
前几天班里有位学生电脑(windows 7系统)出问题了,具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面,长时间没反应,无法进入系统。这个问题原来帮其他同学也解决过,网上搜了不少资料&#x…...
2022/11/19 21:17:04 - 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...
本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法,并在最后教给你1种保护系统安全的好方法,一起来看看!电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中,添加了1个新功能在“磁…...
2022/11/19 21:17:03 - 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...
许多用户在长期不使用电脑的时候,开启电脑发现电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机。。.这要怎么办呢?下面小编就带着大家一起看看吧!如果能够正常进入系统,建议您暂时移…...
2022/11/19 21:17:02 - 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...
配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!配置windows update失败 还原更改 请勿关闭计算机&#x…...
2022/11/19 21:17:01 - 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...
不知道大家有没有遇到过这样的一个问题,就是我们的win7系统在关机的时候,总是喜欢显示“准备配置windows,请勿关机”这样的一个页面,没有什么大碍,但是如果一直等着的话就要两个小时甚至更久都关不了机,非常…...
2022/11/19 21:17:00 - 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...
当电脑出现正在准备配置windows请勿关闭计算机时,一般是您正对windows进行升级,但是这个要是长时间没有反应,我们不能再傻等下去了。可能是电脑出了别的问题了,来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...
2022/11/19 21:16:59 - 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...
我们使用电脑的过程中有时会遇到这种情况,当我们打开电脑之后,发现一直停留在一个界面:“配置Windows Update失败,还原更改请勿关闭计算机”,等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢࿰…...
2022/11/19 21:16:58 - 如何在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