Java的集合

集合

可以动态保存任意多个对象,使用比较方便

提供了一系列方便的操作对象的方法: addremovesetget 等,添加/删除新元素简洁了


Java 的集合类很多,主要分为两大类 CollectionMap

Collection 接口有两个重要的子接口List Set , 他们的实现子类都是单列集合 (单列数据)

Map 接口的实现子类是双列集合,存放的K-V (双列数据)



Collection

public interface Collection <E> extends lterable <E>
  • collection实现子类可以存放多个元素,每个元素可以是Object
  • Collection接口没有直接的实现子类,是通过它的子接口 SetList 来实现的

Collection方法

由于Collection没有直接子类,ListCollection的子接口实现,因此这里用List展示Collection类方法

import java.util.ArrayList;
import java.util.List;public class CollectionMethod {@SuppressWarnings({"all"})public static void main(String[] args) {List list = new ArrayList();// add:添加单个元素list.add("jack");list.add(10);//list.add(new Integer(10)) 本质是对象list.add(true);System.out.println("list=" + list);// remove:删除指定元素list.remove(0);//删除第一个元素 返回boolenlist.remove(true);//指定删除某个元素 返回该objSystem.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("三国演义");list.addAll(list2);System.out.println("list=" + list);// containsAll:查找多个元素是否都存在System.out.println(list.containsAll(list2));//T// removeAll:删除多个元素list.add("聊斋");list2.add("时间是金");list.removeAll(list2);System.out.println("list=" + list);//[聊斋]}
}

Collection遍历

  • Iterator

迭代器,主要用于遍历Collection集合中的元素。

所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了lterator接口的对象,即可以返回一个迭代器。

在调用iterator.next()方法之前必须要调用iterator.hasNext()进行检测。

若不调用,且下一条记录无效,直接调用iterator.next()会抛出NoSuchElementException 异常。

  • for 循环增强

增强for循环,可以代替iterator迭代器

特点:增强for就是简化版的iterator,本质一样。只能用于遍历集合或数组。

for(元素类型 元素名:集合名或数组名){
}






List

List 接口是 Collection接口的子接口

List集合类中元素有序(即添加顺序和取出顺序一致)、且可重复

List集合中的每个元素都有其对应的顺序索引,即支持索引

List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素

List 方法

  • void add(int index, Object ele):在index位置插入ele元素
  • boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来
  • Object get(int index):获取指定index位置的元素
  • int indexOf(Object obj):返回obj在集合中首次出现的位置
  • int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置
  • Object remove(int index):移除指定index位置的元素,并返回此元素
  • Object set(int index, Object ele):设置指定index位置的元素为ele , 相当于是替换.
  • List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的子集合。(fromIndex <= subList < toIndex)

这部分方法是List独有的,set用不了



ArrayList

ArrayList 可以加入null(空值),并且可以是多个

ArrayList是由数组来实现数据存储的

ArrayList基本等同于Vector,除了ArrayList是线程不安全(执行效率高)。在多线程情况下,不建议使用ArrayList

ArrayList中维护了一个Object类型的数组elementData

分析

当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第1次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData1.5倍

如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData1.5倍



Vector

public class vector<E>extends AbstractList<E>
implements List<E>RandomAccess,cloneable,Serializable

分析

Vector底层也是一个对象数组, protected Object[] elementData;

Vector是线程同步的,即线程安全, Vector类的操作方法带有

synchronizedpublic synchronized E get(int index){
if (index >= elementCount)throw new ArraylndexOutOfBoundsException(index);
return elementData(index);
}

比较

底层架构版本线程安全(同步)效率扩容倍数
ArrayList可变数组jdk1.2不安全,效率高如果是无参,默认10,第二次开始按1.5倍扩容。如果指定大小,则每次直接按1.5倍扩容
Vector可变数组 Object[]jdk1.0安全,效率不高如果是无参,默认10,满后就按2倍扩容。如果指定大小,则每次直接按两倍扩容



LinkedList

LinkedList底层实现了双向链表和双端队列特点,可以添加任意元素(元素可以重复),包括null

线程不安全,没有实现同步

分析

LinkedList中维护了两个属性firstlast分别指向首节点和尾节点

每个节点(Node对象),里面又维护了prevnextitem三个属性,其中通过prev指向前一个,通过next指向后一个节点,最终实现双向链表,所以LinkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高。

比较

底层架构增删的效率改查的效率
ArrayList可变数组较低 数组扩容较高
LinkedList双向链表较高 链表追加较低
  • 如果我们改查的操作多,选择ArrayList
  • 如果我们增删的操作多,选择LinkedList
  • 一般来说,在程序中,80%-90%都是查询,因此大部分情况下会选择ArrayList






Set

无序(添加和取出的顺序不一致),没有索引,不允许重复元素,所以最多包含一个null

Set 方法

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

Set遍历

同Collection的遍历方式一样,因为Set接口是Collection接口的子接口。

可以使用迭代器或增强for,不能使用索引的方式来获取


HashSet

HashSet实际上是HashMap

public Hashset() {map = new HashMap<>();
}

可以存放null值,但是只能有一个null

HashSet不保证元素是有序的,取决于hash后,再确定索引的结果。(即,不保证存放元素的顺序和取出顺序一致)

分析

添加一个元素时,先得到hash值-会转成->索引值

找到存储数据表table,看这个索引位置是否已经存放的有元素,如果没有,直接加入

如果有,调用equals比较,如果相同,就放弃添加,`如果不相同,则添加到最后

在Java8中,如果一条链表的元素个数到达 TREEIFY_THRESHOLD(默认是8),并且table的大小>=MIN TREEIFY CAPACITY(默认64),就会进行树化(红黑树),否则仍然会采用数组扩容机制。

HashSet底层是HashMap,第一次添加时,table数组扩容到16,临界值(threshold)是16* 加载因子 (loadFactor)是0.75 = 12

如果table数组使用到了临界值12,就会扩容到16* 2=32,新的临界值就是32*0.75 =24。依次类推

package com.hspedu.set_;import java.util.HashSet;@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) 可见这个hash的值并不是hashcode,而是做了一定的处理 >>> 16.public V put(K key, V value) {//key = "java" value = PRESENT 共享return putVal(hash(key), key, value, false, true);}4.执行 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; //定义了辅助变量//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); // 这个null类似与模拟节点的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;}*/}
}



LinkedHashSet

LinkedHashSetHashSet的子类

LinkedHashSet 底层是一个 LinkedHashMap,底层维护了一个数组+双向链表

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

LinkedHashSet不允许添重复元素

分析

LinkedHastSet中维护了一个hash表和双向链表( LinkedHashSetheadtail)

每一个节点有beforeafter属性,这样可以形成双向链表

在添加一个元素时,先求hash值,在求索引,确定该元素在table的位置,然后将添加的元素加入到双向链表(如果已经存在,不添加[原则和hashset一样])

这样的话,我们遍历LinkedHashSet 也能确保插入顺序和遍历顺序一致






Map

MapCollection并列存在。用于保存具有映射关系的数据:Key-Value

Map接口的常用实现类:HashMapHashtableProperties

Map中的key不允许重复,原因和HashSet一样,value可以重复

Mapkey可以为null, value也可以为null,注意keynull,只能有一个,valuenull ,可以多个

常用String类作为Mapkey

keyvalue之间存在单向一对一关系,即通过指定的 key总能找到对应的value

Map 中的keyvalue可以是任何引用类型的数据,会封装到HashMap$Node对象中,又因为Node实现了Entry 接口,有些书上也说一对 k-v 就是一个Entry

但是本质上Entry还是指向HashMap$Node中的元素,并不是复制版存储。


Map方法

import java.util.HashMap;
import java.util.Map;@SuppressWarnings({"all"})
public class MapMethod {public static void main(String[] args) {//演示map接口常用方法Map map = new HashMap();map.put("fh", new Book("", 100));//OKmap.put("fh", "bnd");//替换-> 一会分析源码map.put("fgd", "mr");//OKmap.put("sgfh", "mr");//OKmap.put("vcbhhd", null);//OKmap.put(null, "dfhdfg");//OKmap.put("lh", "gct");//OKmap.put("hsp", "hspd");System.out.println("map=" + map);// remove:根据键删除映射关系map.remove(null);System.out.println("map=" + map);
// get:根据键获取值Object val = map.get("lh");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;}
}

Map遍历

  • containsKey 查找键是否存在
  • keySet 获取所有的键
  • entrySet 获取所有关系k-v
  • values 获取所有的值



HashMap

HashMapMap 接口使用频率最高的实现类。

HashMap 是以key-val对的方式来存储数据(HashMap$Node类型)

key不能重复,但是值可以重复,允许使用null键和null

如果添加相同的key,则会覆盖原来的key-val,等同于修改(key不会替换,val会替换)

HashSet一样,不保证映射的顺序,因为底层是以hash表的方式来存储的. (jdk8的hashMap底层数组+链表+红黑树)

HashMap没有实现同步,因此是线程不安全的,方法没有做同步互斥的操作,没有synchronized

分析

HashMap 底层维护了Node类型的数组table,默认为null

当创建对象时,将加载因子(Ioadfactor)初始化为0.75.

当添加key-val时,通过key的哈希值得到在table的索引。然后判断该索引处是否有元素,如果没有元素直接添加。

如果该索引处有元素,继续判断该元素的key和准备加入的key是否相等,如果相等,则直接替换val

如果不相等需要判断是树结构还是链表结构,做出相应处理。如果添加时发现容量不够,则需要扩容。

第1次添加,则需要扩容table容量为16,临界值(threshold)为12 (16*0.75)

以后再扩容,则需要扩容table容量为原来的2倍(32),临界值为原来的2倍,即24,依次类推.

在Java8中,如果一条链表的元素个数超过 TREEIFY_THRESHOLD(默认是8),并且table的大小>= MIN TREEIFY CAPACITY(默认64),就会进行树化(红黑树)

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();}*/}
}



HashTable

存放的元素是键值对:即K-V

hashtable的键和值都不能为null,否则会抛出NullPointerException

hashTable使用方法基本上和HashMap一样

hashTable是线程安全的(synchronized), hashMap是线程不安全的

比较

版本线程安全(同步)效率允许null键null值
Hashmap1.2不安全可以
Hashtable1.0安全较低不可以



Properties

Properties类继承自 Hashtable 类并且实现了Map接口,也是使用一种键值对的形式来保存数据。

使用特点和Hashtable类似。

Properties还可以用于从xxx.properties文件中,加载数据到Properties类对象, 并进行读取和修改。

xxx.properties文件通常作为配置文件






TreeSet

package com.hspedu.set_;import java.util.Comparator;
import java.util.TreeSet;
@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);}
}






TreeMap

package com.hspedu.map_;import java.util.Comparator;
import java.util.TreeMap;@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 工具类

Collections是一个操作 SetListMap等集合的工具类。

Collections中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作。

排序操作(均为static 方法)

reverse(List) 反转List中元素的顺序
shuffle(List) 对List集合元素进行随机排序
sort(List) 根据元素的自然顺序对指定List集合元素按升序排序
sort(List,Comparator) 根据指定的Comparator产生的顺序对List 集合元素进行排序
swap(List,int,int) 将指定 list集合中的i处元素和j处元素进行交换

查找、替换

Object max(Collection) 根据元素的自然顺序,返回给定集合中的最大元素
Object max(Collection,Comparator) 根据Comparator指定的顺序,返回给定集合中的最大元素
Object min(Collection) 根据元素的自然顺序,返回给定集合中的最小元素
Object min(Collection,Comparator) 根据Comparator指定的顺序,返回给定集合中的最小元素
int frequency(Collection,Object 返回指定集合中指定元素的出现次数
void copy(List dest,List src) 将src中的内容复制到dest中
boolean replaceAll(List list,Object oldVal,Object newVal) 使用新值替换List 对象的所有旧值

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/32509.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深眸科技|发现AI+3D视觉的价值,技术升级加速视觉应用产品国产替代

随着中国工业化进程的不断深入和智能制造浪潮的影响&#xff0c;工业生产对于机器视觉技术的需求不断攀升&#xff0c;其应用范围覆盖了工业领域的众多行业&#xff0c;包括3C电子、汽车、半导体、新能源、物流等。 据GGII发布的最新数据显示&#xff0c;近年来我国机器视觉市…

最强自动化测试框架Playwright(4)-上下文及窗口处理

browser.new_context() 创建一个新的浏览器上下文。它不会与其他浏览器上下文共享 cookies/缓存。 context之间是相互隔离的&#xff0c;可以理解为轻量级的浏览器实例 多浏览器窗口 创建一个context相当于打开一个新的浏览器窗口 如下代码打开两个浏览器窗口&#xff1a; …

JavaScript面试题(一)

1、解释一下什么是闭包 ? 闭包&#xff1a;就是能够读取外层函数内部变量的函数。 闭包需要满足三个条件&#xff1a; 访问所在作用域&#xff1b; 函数嵌套&#xff1b; 在所在作用域外被调用 。 优点&#xff1a;可以重复使用变量&#xff0c;并且不会造成变量污染 。 …

通达OA SQL注入漏洞【CVE-2023-4165】

通达OA SQL注入漏洞【CVE-2023-4165】 一、产品简介二、漏洞概述三、影响范围四、复现环境POC小龙POC检测工具: 五、修复建议 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损…

029 - integer types 整数类型

MySQL支持SQL标准整数类型 INTEGER&#xff08;或INT&#xff09;和 SMALLINT。作为一个可扩展标准&#xff0c;MySQL也支持整数类型 TINYINT&#xff0c;MEDIUMINT和 BIGINT。下表显示了每种整数类型所需的存储空间和范围。 表11.1 MySQL支持的整数类型的必需存储和范围 类型…

电脑麦克风没声音?

这3招就可以解决&#xff01; 在我们使用电脑录制视频时&#xff0c;有时会遇到一个令人头疼的问题&#xff1a;麦克风没有声音。那么&#xff0c;为什么会出现这种情况呢&#xff1f;更重要的是&#xff0c;我们应该如何解决这个问题呢&#xff1f;本文将介绍3种方法&#xf…

【钉钉接口】bpms_task_change、bpms_instance_change 的区别及举例

bpms_task_change&#xff1a;审批任务回调&#xff0c;是针对审批任务状态的推送。如审批人执行审批、审批人转交审批等针对具体某个审批节点的操作&#xff0c;属于 bpms_task_change 事件类型。bpms_instance_change&#xff1a;审批实例回调&#xff0c;是针对审批实例状态…

内生性的蒙特卡罗模拟

这是一个很好的例子,通过蒙特卡洛模拟展示了忽略相关变量时,回归系数估计的偏差。 %% 蒙特卡洛模拟&#xff1a;内生性会造成回归系数的巨大误差 times 300; % 蒙特卡洛的次数 R zeros(times,1); % 用来储存扰动项u和x1的相关系数 K zeros(times,1); % 用来储存遗漏了x2…

数据结构和算法三(排序)

列表排序 排序类型&#xff1a; 一、冒泡排序&#xff1a; 屏幕录制2023-07-25 13.05.12 def bubble_sort(li):exchangeFalseif len(li)<1:return lifor i in range(len(li)-1):for j in range(len(li)-i-1):if li[j]>li[j1]:li[j],li[j1]li[j1],li[j]print(li)exchangeT…

【C语言学习】函数原型

函数原型 代码一 #include<stdio.h> void sum(int begin, int end) {int i;int sum 0;for(ibegin; i<end; i){sum sum i;}printf("%d到%d的和是%d\n", begin, end, sum); }int main() {sum(1,10);sum(20,30);sum(40,50);return 0; }代码二&#xff08;函…

【黑马头条之xxl-Job分布式任务调度】

本笔记内容为黑马头条项目的分布式任务调度热点文章部分 目录 一、今日内容 1、需求分析 2、实现思路 3、定时计算 4、定时任务框架-xxljob 二、分布式任务调度 1、什么是分布式任务调度 2、xxl-Job简介 3、XXL-Job-环境搭建 4、配置部署调度中心-docker安装 5、xx…

C#实现邮箱验证码

开发环境&#xff1a;C#&#xff0c;VS2019&#xff0c;.NET Core 3.1&#xff0c;ASP.NET Core Web API&#xff0c;163邮箱 1、在163邮箱的设置中开通IMAP/SMTP的服务&#xff0c;授权成功后会弹出一个窗体&#xff08;如下图所示&#xff09;&#xff0c;上面显示了授权密码…

【数据可视化】(二)数据探索组件

目录 0.简介 一、数据模式与数据组织 1、数据的定义 2、数据库的定义 3、什么是数据模式? 4、数据模式举例 5、什么是数据纲要? 6、数据组织的层次 二、矢量数据 1、什么是矢量数据?

docker 容器中执行命令出现错误: 13: Permission denied

错误 13: Permission denied [rootVM-32-11-tencentos ~]# docker exec -it kibana1 /bin/bash kibana76c20c215dcb:~$ apt-get install vi E: Could not open lock file /var/lib/dpkg/lock-frontend - open (13: Permission denied) E: Unable to acquire the dpkg frontend…

JavaScript、TypeScript、ES5、ES6之间的联系和区别

ECMAScript&#xff1a; 一个由 ECMA International 进行标准化&#xff0c;TC39 委员会进行监督的语言。通常用于指代标准本身。JavaScript&#xff1a; ECMAScript 标准的各种实现的最常用称呼。这个术语并不局限于某个特定版本的 ECMAScript 规范&#xff0c;并且可能被用于…

126、高频Redis面试题:如何保证Redis和数据库数据一致性

高频Redis面试题:如何保证Redis和数据库数据一致性 缓存用法如何更新缓存先更新缓存&#xff0c;再更新数据库先更新数据库&#xff0c;再更新缓存先删除缓存&#xff0c;再更新数据库延时双删&#xff08;删除缓存&#xff0c;更新数据库&#xff0c;再延时删除缓存&#xff0…

flask-----初始项目架构

1.初始的项目目录 -apps 包 ------存放app -user文件夹 -------就是一个app -models.py --------存放表模型 -views.py -------存放主代码 -ext包 -init.py -------实例化db对象 -manage.py -----运行项目的入口 -setting.py -----配置文件 2.各文件内容 manage…

【JavaSE】数组的定义与使用

详解数组 数组的基本概念什么是数组数组的创建及初始化数组的使用 数组是引用类型基本类型变量与引用类型变量的区别引用变量认识 null 数组的应用场景数组练习二维数组 数组的基本概念 什么是数组 数组可以看成是相同类型元素的一个集合。在内存中是一段连续的空间。比如现实…

深入解析搜好货API:开启智能化电商解决方案

随着电商行业的快速发展&#xff0c;人们对于个性化、智能化的购物体验的追求也越来越高。为了满足消费者的需求&#xff0c;搜好货API应运而生。 一、搜好货API的基本原理 搜好货API基于先进的数据挖掘和机器学习算法&#xff0c;通过收集和分析大量的商品信息和用户行为数据…

【数学建模】--聚类模型

聚类模型的定义&#xff1a; “物以类聚&#xff0c;人以群分”&#xff0c;所谓的聚类&#xff0c;就是将样本划分为由类似的对象组成的多个类的过程。聚类后&#xff0c;我们可以更加准确的在每个类中单独使用统计模型进行估计&#xff0c;分析或预测&#xff1b;也可以探究不…