Java中List集合有哪些特性?(内含视频教程)

本文将为大家详细讲解Java中的List集合,这是我们进行开发时经常用到的知识点,也是大家在学习Java中很重要的一个知识点,更是我们在面试时有可能会问到的问题。

文章较长,干货满满,建议大家收藏慢慢学习。文末有本文重点总结,主页有全系列文章分享。技术类问题,欢迎大家和我们一起交流讨论!

前言

在上一篇文章中给大家介绍了Java里的集合,我们了解了集合的由来、特点,以及一些接口API等,但这些内容都偏重于理论。 那么从今天这篇文章开始,我们会从实战的角度来进行List集合的学习。可以说,List集合是开发时用的最多的一种集合,尤其是ArrayList更是被经常使用。

所以对今天的内容,希望大家要好好阅读和练习

全文大约 【5800】 字,不说废话,只讲可以让你学到技术、明白原理的纯干货!本文带有丰富的案例及配图视频,让你更好地理解和运用文中的技术概念,并可以给你带来具有足够启迪的思考...

一. List集合简介

1. 概述

List本身是一个接口,该接口继承自Collection接口,它有两个常用的实现子类ArrayList和LinkedList。从功能特性上来看,List是有序、可重复的单列集合,集合中的每个元素都有对应的顺序索引,我们可以通过该索引来访问指定位置上的集合元素。默认情况下,List会按元素的添加顺序给元素设置索引,第一个添加到List集合中的元素索引为0,第二个为1,后面依此类推。所以List的行为和数组几乎完全相同,它们都是有序的存储结构。另外List集合中允许有重复的元素,甚至可以有多个null值

但是如果我们是使用数组来添加和删除元素,就会非常的不方便。比如从一个已有的数组{'A', 'B', 'C', 'D', 'E'}中删除索引为2的元素,这个“删除”操作实际上是把'C'后面的元素依次往前挪一个位置;而“添加”操作实际上是把指定位置以后的元素依次向后挪一个位置,腾出位置给新加入的元素。针对这两种操作,使用数组实现起来都会非常麻烦。所以在实际应用中,我们增删元素时,一般都是使用有序列表(如ArrayList),而不是使用数组。

2. 类关系

我们来看看List接口的类关系,如下图所示:

image.png

从这个类关系中我们可以看到,List接口继承了Collection接口,并且有ArrayList、LinkedList、Vector等子类,其中Vector现在已经不太常用了,所以我们重点掌握ArrayListLinkedList就行。

3. 常用API方法

在List接口中定义了子类的一些通用方法,如下所示:

  • boolean add(E e) :在集合末尾添加一个数据元素;
  • boolean add(int index, E e) :在集合的指定索引出添加一个数据元素;
  • E remove(int index) :删除集合中指定索引的元素;
  • boolean remove(Object e) :删除集合中的某个元素;
  • E get(int index) :获取集合中指定索引出的元素;
  • int size() :获取集合的大小(包含元素的个数)。

以上这些方法,就是我们在开发时比较常用的几个方法,一定要记住

4. List对象创建方式

List作为一个接口,我们通常不能直接new List来创建其对象,在Java中给我们提供了如下两种创建List对象的方式:

  • 通过多态方式创建:new List的某个子类,比如new ArrayList()等;
  • 通过List.of()方法创建:of()方法可以根据给定的数据元素快速创建出List对象,但该方法不接受null值,如果传入null会抛出NullPointerException异常。
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class Demo01 {
	public static void main(String[] args) {
		//创建List对象方式一:
		List<String> list1=new ArrayList<>();
		
		List<String> list2=new LinkedList<>();
		
		//创建List对象方式二:
		List<Integer> list3 = List.of(1,3,5,7,9);

    	//该方式不能传入null参数,否则会产生NullPointerException异常
		//List<Integer> list4 = List.of(1,3,5,7,9,null);
	}
}

5. List集合遍历方式

很多时候,我们都会对集合进行遍历操作,也就是要把集合中的每个元素挨个的取出来,以下是几种常用的集合遍历方式:

  • 普通for循环配合get(索引值)方法进行遍历: 这种遍历方式实现起来代码较为复杂,且get(int)取值方法只对ArrayList比较高效,但对LinkedList效率较低,索引越大时访问速度越慢。
  • 增强for循环进行遍历: 我们也可以使用增强for循环进行遍历,该方式比普通for循环实现起来更为简洁。
  • 使用Iterator迭代器进行集合遍历: 不同的List对象调用iterator()方法时,会返回不同实现的Iterator对象,该Iterator对象对集合总是具有最高的访问效率。
import java.util.Iterator;
import java.util.List;

public class Demo02 {
	public static void main(String[] args) {
		//List遍历方式一,普通for循环:
		List<String> list = List.of("java", "大数据", "壹壹哥");
		for(int i=0;i<list.size();i++) {
			System.out.println("遍历方式一,值="+list.get(i));
		}
		
		//List遍历方式二,迭代器:
		Iterator<String> it = list.iterator();
        while(it.hasNext()){
        	//取出下一个值
            String value = it.next();
            System.out.println("遍历方式二,值="+value);
        }

        //List遍历方式三,增强for循环:内部会自动使用Iterator
		for(String item:list) {
			System.out.println("遍历方式三,item="+item);
		}
	}
}

上面提到的Iterator对象,有两个常用方法,如下所示:

boolean hasNext(): 该方法用于判断集合中是否还有下一个元素;
E next(): 该方法用于返回集合的下一个元素。

虽然使用Iterator遍历List集合的代码,看起来比使用索引较复杂,但Iterator遍历List集合的效率却是最高效的方式。

另外只要是实现了Iterable接口的集合类,我们都可以直接使用for each增强循环来遍历。在增强for循环中,Java编译器会自动把for each循环变成基于Iterator方式的遍历方式。

6. List与数组的转换方式

其实List与Array数组在很多地方都是比较相似的,比如都可以根据索引对数据元素进行遍历取值等操作。因为存在着这种相似之处,所以在List和数组之间是可以互相转换的,即List集合可以转成数组,数组也可以转成List集合。

6.1 List转数组

一般情况下,List转数组有如下几种方式:

  • toArray() 方法:该方法会返回一个Object[]数组,但该方法会丢失类型信息,在实际开发时较少使用;
  • toArray(T[])方法:传入一个与集合的数据元素类型相同的Array,List会自动把元素复制到传入的Array中;
  • T[] toArray(IntFunction<T[]> generator) 方法:函数式写法,这是Java中的新特性,后面我们会单独讲解。大家可以持续关注
import java.util.List;

public class Demo03 {
	public static void main(String[] args) {
		List<String> list = List.of("java", "大数据", "壹壹哥");
		
		// List转数组方式一:返回一个Object[]数组
		Object[] array = list.toArray();
        for (Object val : array) {
            System.out.println("方式一,value="+val);
        }
        
        // List转数组方式二,给toArray(T[])传入与数组元素类型相同的Array,如果数组类型与集合数据元素类型不匹配则会产生如下异常:
        // java.lang.ArrayStoreException: arraycopy: element type mismatch: 
        //can not cast one of the elements of java.lang.Object[] to the type of the destination array, java.lang.Integer
        String[] array2 = list.toArray(new String[list.size()]);
        for (String val : array2) {
            System.out.println("方式二,value="+val);
        }
        
        // List转数组方式三:返回一个String[]数组
        String[] array3 = list.toArray(String[]::new);
        for (String val : array3) {
            System.out.println("方式二,value="+val);
        }
	}
}

在本案例中,第一种实现方式是调用toArray()方法直接返回一个Object[]数组,但这种方法会丢失类型信息,所以开发是很少使用。

第二种方式要给toArray(T[])方法传入一个与集合数据元素类型相同的Array,List内部会自动把元素复制到传入的Array数组中。如果Array类型与集合的数据元素类型不匹配,就会产生”java.lang.ArrayStoreException: arraycopy: element type mismatch: can not cast one of the elements of java.lang.Object[] to the type of the destination array......“异常。

第三种方式是通过List接口定义的T[] toArray(IntFunction<T[]> generator)方法,这是一种函数式写法,以后再单独给大家讲解。可以持续关注我们哦

6.2 数组转List

反过来,数组也可以转为List集合,一般的方式如下:

  • List.of(T...)方法:该方法会返回一个只读的List集合,如果我们对只读List调用add()、remove()方法会抛出UnsupportedOperationException异常。其中的T是泛型参数,代表要转成List集合的数组;
  • Arrays.asList(T...) 方法:该方法也会返回一个List集合,但它返回的List不一定就是ArrayList或者LinkedList,因为List只是一个接口。
import java.util.Arrays;
import java.util.List;

public class Demo04 {
	public static void main(String[] args) {
		// 数组转List的方式一:List.of()返回一个只读的集合,不能进行add/remove等修改操作。
		List<Integer> values = List.of(1,8,222,10,5);
        for (Integer val : values) {
            System.out.println("方式一,value="+val);
            
            //该集合是一种只读的集合,不能在遍历时进行增删改等更新操作,只能进行读取操作,
            //否则会产生java.lang.UnsupportedOperationException异常
            //values.remove(0);
        }
        
        // 数组转List的方式二:Arrays.asList()返回一个只读的集合,不能进行add/remove等修改操作。
        List<String> items = Arrays.asList("java","壹壹哥","元宇宙");
        for (String item : items) {
            System.out.println("方式二,value="+item);
            
            //不可以进行增删改操作
            //items.add("sss");
            //items.remove(0);
        }
	}
}

在本案例中,无论我们是通过List.of()方法,还是通过Arrays.asList()方法,都只会返回一个只读的集合。这种集合在遍历时不能进行增删改等更新操作,只能进行读取操作,否则会产生java.lang.UnsupportedOperationException异常。

二. ArrayList集合

1. 简介

ArrayList是一个数组队列,位于java.util包中,它继承自AbstractList,并实现了List接口。其底层是一个可以动态修改的数组,该数组与普通数组的区别,在于它没有固定的大小限制,我们可以对其动态地进行元素的添加或删除

image.png

存储在集合内的数据被称为”元素“,我们可以利用索引来访问集合中的每个元素。为了方便我们操作这些元素,ArrayList给我们提供了相关的添加、删除、修改、遍历等功能。

因为ArrayList的底层是一个动态数组,所以该集合适合对元素进行快速的随机访问(遍历查询),另外尾部成员的增加和删除操作速度也较快,但是其他位置上元素的插入与删除速度相对较慢。基于这种特性,所以ArrayList具有查询快,增删慢的特点

2. 常用方法

ArrayList给我们提供了如下这些方法,我们可以先来了解一下:

方法 描述
add() 将数据元素插入到ArrayList的指定位置上
addAll() 将一个新集合中的所有元素添加到ArrayList中
clear() 删除ArrayList中所有的元素
contains() 判断元素是否在ArrayList中
get() 通过索引值获取ArrayList中的元素
indexOf() 返回ArrayList中某个元素的索引值
removeAll() 删除ArrayList中指定集合的所有元素
remove() 删除ArrayList里的单个元素
size() 返回ArrayList的元素数量
isEmpty() 判断ArrayList是否为空
subList() 截取ArrayList的部分元素
set() 替换ArrayList中指定索引的元素
sort() 对ArrayList的数据元素进行排序
toArray() 将ArrayList转换为数组
toString() 将ArrayList转换为字符串
ensureCapacity() 设置指定容量大小的ArrayList
lastIndexOf() 返回指定元素在ArrayList中最后一次出现的位置
retainAll() 保留指定集合中的数据元素
containsAll() 查看ArrayList是否包含了指定集合的所有元素
trimToSize() 将ArrayList的容量调整为数组的元素个数
removeRange() 删除ArrayList中指定索引间存在的元素
replaceAll() 用给定的数据元素替换掉指定数组中每个元素
removeIf() 删除所有满足特定条件的ArrayList元素
forEach() 遍历ArrayList中每个元素并执行特定操作

接下来我们就挑选几个常用的方法,通过几个案例来给大家讲解一下ArrayList的用法。

3. 添加元素

ArrayList给我们提供了多个与添加相关的方法,比如add()和addAll()方法,可以将元素添加到集合中。另外如果我们要计算ArrayList中元素的数量,可以使用size()方法。

import java.util.ArrayList;

public class Demo05 {
	public static void main(String[] args) {
		//创建ArrayList集合,<String>中的是泛型,后面我们会专门讲解泛型
		ArrayList<String> names = new ArrayList<String>();
		//一个一个地添加元素
		names.add("一一哥");
		names.add("java");
		names.add("数学");
        
		//遍历集合
        for (String name : names) {
            System.out.println("name="+name+",size="+names.size());
        }
        
        ArrayList<String> names2 = new ArrayList<String>();
        names2.add("壹壹哥");
        //在A集合中追加B集合
        names2.addAll(names);
        
        //遍历集合
        for (String name : names2) {
            System.out.println("name="+name);
        }
	}
}

在上面的代码中,这部分是泛型,会在后面给大家专门讲解,敬请期待哦。

4. 遍历元素

我们对ArrayList中元素进行遍历的方式,其实与List的遍历是一样的,我们可以使用普通for循环、增强for循环、Iterator迭代器等方式对集合进行遍历,这里我们就不再单独展示其用法了。

5. 修改元素

我们使用add()方法将元素添加到集合中之后,如果想对集合中的元素进行修改,可以使用set()方法。

import java.util.ArrayList;

public class Demo06 {
	public static void main(String[] args) {
		//创建ArrayList集合,<String>中的是泛型,后面我们会专门讲解泛型
		ArrayList<String> names = new ArrayList<String>();
		//一个一个地添加元素
		names.add("一一哥");
		names.add("java");
		names.add("数学");
		
		//修改集合中的元素:第一个参数是集合中的索引,第二个是要修改的值
		names.set(1, "Android"); 
		names.set(2, "iOS"); 
        
		//遍历集合
        for (String name : names) {
            System.out.println("name="+name);
        }
	}
}

6. 删除元素

如果我们要删除ArrayList中的元素,可以使用remove()、removeAll()等方法。

import java.util.ArrayList;

public class Demo07 {
	public static void main(String[] args) {
		//创建ArrayList集合,<String>中的是泛型,后面我们会专门讲解泛型
		ArrayList<String> names = new ArrayList<String>();
		//一个一个地添加元素
		names.add("一一哥");
		names.add("java");
		names.add("数学");
		
		//删除集合中指定位置上的某个元素
		names.remove(0);
		//删除集合中的某个指定元素
		names.remove("java");
        
		//遍历集合
        for (String name : names) {
            System.out.println("name="+name);
        }
        
        ArrayList<String> names2 = new ArrayList<String>();
        names2.add("语文");
		names2.add("英语");
		names2.add("数学");
		//删除本集合中的另一个集合
        names2.removeAll(names);
        //遍历集合
        for (String name : names2) {
            System.out.println("name2="+name);
        }
	}
}

7. 集合排序

我们可以使用Collections.sort()方法对集合进行升序排列。

import java.util.ArrayList;
import java.util.Collections;

public class Demo08 {

	public static void main(String[] args) {
		//创建ArrayList集合
		ArrayList<Integer> nums = new ArrayList<>();
		//一个一个地添加元素
		nums.add(100);
		nums.add(85);
		nums.add(120);
		nums.add(55);
		
		//对集合进行排序,默认是升序排列
		Collections.sort(nums);  
        
		//遍历集合
        for (Integer num : nums) {
            System.out.println("num="+num);
        }
	}
}

8. 配套视频

本节内容配套视频链接如下:戳链接即可查看

三. LinkedList集合

1. 简介

LinkedList采用链表结构来保存数据,所以是一种链表集合,类似于ArrayList,也是List的一个子类,位于java.util包中。它的底层是基于线性链表这种常见的数据结构,但并没有按线性的顺序存储数据,而是在每个节点中都存储了下一个节点的地址。

image.png

LinkedList的优点是便于向集合中插入或删除元素,尤其是需要频繁地向集合中插入和删除元素时,使用LinkedList类比ArrayList的效率更高。但LinkedList随机访问元素的速度则相对较慢,即检索集合中特定索引位置上的元素速度较慢。

2. LinkedList类关系

LinkedList直接继承自AbstractSequentialList,并实现了List、Deque、Cloneable、Serializable等多个接口。通过实现List接口,具备了列表操作的能力;通过实现Cloneable接口,具备了克隆的能力;通过实现Queue和Deque接口,可以作为队列使用;通过实现Serializable接口,可以具备序列化能力。LinkedList类结构关系如下图所示:

image.png

3. LinkedList与ArrayList对比

与ArrayList相比,LinkedList进行添加和删除的操作效率更高,但查找和修改的操作效率较低。基于这种特性,我们可以在以下情况中使用ArrayList:

  • 需要经常访问获取列表中的某个元素;
  • 只需要在列表的 末尾 进行添加和删除某个元素。

当遇到如下情况时,可以考虑使用LinkedList:

  • 需要经常通过 循环迭代来访问 列表中的某些元素;
  • 需要经常在列表的 开头、中间、末尾 等位置进行元素的添加和删除操作。

4. 常用方法

LinkedList中的很多方法其实都来自于List接口,所以它的很多方法与ArrayList是一样的。但由于其自身特点,也具有一些特有的常用方法,这里只列出LinkedList特有的常用方法,如下表所示:

方法 描述
public void addFirst(E e) 将元素添加到集合的头部。
public void addLast(E e) 将元素添加到集合的尾部。
public boolean offer(E e) 向链表的末尾添加元素,成功为true,失败为false。
public boolean offerFirst(E e) 在链表头部插入元素,成功为true,失败为false。
public boolean offerLast(E e) 在链表尾部插入元素,成功为true,失败为false。
public void clear() 清空链表。
public E removeFirst() 删除并返回链表的第一个元素。
public E removeLast() 删除并返回链表的最后一个元素。
public boolean remove(Object o) 删除某一元素,成功为true,失败为false。
public E remove(int index) 删除指定位置的元素。
public E poll() 删除并返回第一个元素。
public E remove() 删除并返回第一个元素。
public E getFirst() 返回第一个元素。
public E getLast() 返回最后一个元素。
public int lastIndexOf(Object o) 查找指定元素最后一次出现的索引。
public E peek() 返回第一个元素。
public E element() 返回第一个元素。
public E peekFirst() 返回头部元素。
public E peekLast() 返回尾部元素。
public Iterator descendingIterator() 返回倒序迭代器。
public ListIterator listIterator(int index) 返回从指定位置开始到末尾的迭代器。

对这些方法进行基本的了解之后,接下来我们选择几个核心方法来来看看具体该怎么使用。

5. 添加/删除元素

我们可以通过addFirst()和addLast()方法,分别在链表的开头和结尾添加一个元素。当我们要频繁地在一个列表的开头和结尾进行元素添加、删除时,使用````LinkedList要比ArrayList```的效率更高。

import java.util.LinkedList;

public class Demo09 {

	public static void main(String[] args) {
		// 创建LinkedList集合
		LinkedList<String> names = new LinkedList<String>();
		// 一个一个地添加元素
		names.add("一一哥");
		names.add("java");
		names.add("数学");

		//在链表的开头添加元素
        names.addFirst("壹壹哥");
        
        //在链表的结尾添加元素
        names.addLast("历史");

		// 遍历集合
		for (String name : names) {
			System.out.println("name=" + name);
		}

        //移除链表开头的元素
        names.removeFirst();
        //移除链表结尾的元素
        names.removeLast();
	}
}

6. 迭代获取元素

我们可以通过getFirst()、getLast()等方法获取到集合中的第一个、最后一个元素。

import java.util.LinkedList;

public class Demo10 {
	public static void main(String[] args) {
		// 创建LinkedList集合
		LinkedList<String> names = new LinkedList<String>();
		// 一个一个地添加元素
		names.add("一一哥");
		names.add("java");
		names.add("数学");

		System.out.println("first=" + names.getFirst());
		System.out.println("last=" + names.getLast());

		// 迭代遍历集合
		for (String name : names) {
			System.out.println("name=" + name);
		}
	}
}

7. 配套视频

本节内容配套视频链接如下:戳链接直达视频教程


四. 结语

至此我们就把List集合给大家讲解完毕了,最后我们再来看看本文的重点吧:

List是按索引顺序访问的、长度可变的有序列表;

一般开发时,ArrayList比LinkedList的使用更频繁;

List和Array可以相互转换;

集合遍历时有多种方式,增强for循环和Iterator迭代器的效率更高;

ArrayList与LinkedList都是List接口的实现类,都实现了List中所有未实现的方法,但实现的方式有所不同;

ArrayList底层的数据结构基于动态数组,访问元素速度快于LinkedList,在快速访问数据时ArrayList的执行效率比较高;

LinkedList底层的数据结构基于链表,占用的内存空间较大,但批量插入或删除数据时快于ArrayList。当频繁向集合中插入和删除元素时,使用LinkedList比ArrayList的效率更高。


以上就是本文的全部内容啦,大家有技术类问题,欢迎和我们一起交流讨论~

更多技术类干货,关注我!

我是专门分享技术干货的分享君!

本文转载于网络 如有侵权请联系删除

相关文章

  • Python基础训练100题-14

    分享一些Python学习题目实例066:三数排序实例067:交换位置实例068:旋转数列实例069:报数实例070:字符串长度II实例066:三数排序题目:输入3个数a,b,c,按大小顺序输出。程序分析:同实例005。raw=[] foriinrange(3): x=int(input('int%d:'%(i))) raw.append(x) foriinrange(len(raw)): forjinrange(i,len(raw)): ifraw[i]>raw[j]: raw[i],raw[j]=raw[j],raw[i] print(raw) raw2=[] foriinrange(3): x=int(input('int%d:'%(i))) raw2.append(x) print(sorted(raw2))复制实例067:交换位置题目:输入数组,最大的与第一个元素交换,最小的与最后一个元素交换,输出数组。程序分析:无。li=[3,2,5,7,8,1,5] li[-1],li[li.index(min(li))]=li[li.

  • C语言 对数组名取地址

    大家好,又见面了,我是全栈君,祝每个程序员都可以多学几门语言。作者:卿笃军你有没有想过,对一个一维数组名取地址,然后用这个地址进行加减运算。这会出现什么样的结果呢?演示样例:inta[5]={1,2,3,4,5};int*p=(int*)(&a+1);printf(“%d\n”,*(p-1));这个输出会是多少呢?咦?为什么第二行须要强制转化类型呢?答:a是一个一维数组的名字,&a相当于一个指向一维数组的指针。怎么感觉这么熟悉?指向数组的指针,那不就是行指针吗?int(*p)[]。行指针+1,就是对指针进行加减操作,其结果还是一个行指针~~~原来如此,须要强制转换为单指针。能够看一段代码,例如以下:#include<stdio.h> intmain() { inta[5]={1,2,3,4,5}; int*p=(&a+1); return0; }复制编译会出现例如以下警告(警告行数: int*p=(&a+1);): 上面的警告也告诉我们,&a是一个行指针~~~那么,输出结果是多少呢?答:当然是5。为什么?答:上面不是说了嘛,

  • ARM(六).TIMER and IRQ(1)

    前言ARM处理器是英国Acorn有限公司设计的低功耗低成本的一款RISC微处理器ARM全称为AcornRISCMachine因为价格与能耗上的明显优势,在手持设备与嵌入式领域有大规模的应用,可以说目前的绝大部分便携或手持电子消费品都是用的ARM芯片前面一篇简单地对ARM裸机开发、平台环境与工具、创建项目、按键中断的控制与基础进行了演示这里再对定时器与中断进行探究概要定时器和中断要求使用ARM板上的定时器结合中断对蜂鸣器进行控制Timer电路原理图Buzzer电路原理图创建项目创建项目的总体过程就是新建文件夹创建项目文件项目中添加入源代码只有以下几个方面需要稍微注意一下选择三星S3C2440A芯片Device选项卡中确保是正确的设备选型(和头文件相关,寄存器的正确地址决定于此)设定时钟频率和栈大小Target选项卡中确保时钟频率和板载一致正确设定内存(只读栈和读写栈,也就是代码区与数据区的大小)选择H-JTAGARM模式选择正确的模式使用外部工具代码示例timer_irq.s这是主汇编程序,定义了中断向量表,进行了各种初始化 GET s3c2410_SFR.s ;GET伪指令将s3c

  • 搭建自己的技术博客系列(六)酷炫主题icarus常用配置整合版,快速搞定博客首页

    搭建自己的技术博客系列(六)酷炫主题icarus常用配置整合版,快速搞定博客首页 40/100 发布文章 a724888 _config.xml 这里首先要知道在Hexo中有两份主要的配置文件,其名称都是_config.yml,它们均是用于站点配置使用的。其中,一份位于站点根目录下(比如我的:D:\h2pl.github.io_config.yml),主要包含Hexo本身整站的配置;另一份位于主题目录(D:\hexo\themes\icaurs_config.yml)下,这份配置由主题作者提供,主要用于配置主题相关的选项。为了描述方便,在以下说明中,将前者称为站点配置文件,后者称为主题配置文件。下面我们先来看看站点配置文件的配置修改。 在这里插入图片描述#HexoConfiguration复制 ##Docs:https://hexo.io/docs/configuration.html复制 ##Source:https://github.com/hexojs/hexo/复制 #HexoConfiguration复制 ##Docs:https://hexo.io/docs/configu

  • Mysql索引使用的正确姿势

    今天给大家简单的介绍一下mysql的索引用法,像在我们日常业务开发中,最核心的其实就是写SQL命令,但是你写的SQL真的用到索引了吗?索引实现原理mysql数据库索引实现是在存储引擎中完成的,今天主要以InnoDB存储引擎为例给大家介绍一下。InnoDB存储引擎索引的实现采用B+树数据结构,今天我们主要讲应用,如果想要深究原理的童鞋,可以自己研究研究。索引失效索引失效的场景,基本属于老生常谈了,我这边就再啰嗦一遍:少用or,用它来连接时索引会失效。like查询以%开头。字符串不加单引号索引失效。如果mysql估计使用全表扫描要比使用索引快,则不使用索引。在MYSQL使用不等于(<,>,!=)的时候无法使用索引,会导致索引失效。isnull或者isnotnull也会导致无法使用索引。不在索引列上做任何操作(计算,函数,(自动或者手动)类型装换),会导致索引失效而导致全表扫描。最佳左前缀法则——如果索引了多列,要遵守最左前缀法则。索引优化原则给需要的字段加索引一般需要加索引的都是where中经常使用的字段,但是像性别这种属性字段,加索引的意义不大,因为性别这类字段选择性太低(基

  • python3验证码机器学习 python3验证码机器学习

    python3验证码机器学习文档结构为--iconset --... --jpg --captcha.gif --py --crack.py复制需要的库pip3installpilloworeasy_installPillow必须文件下载地址python3验证码机器学习1.读取图片,打印图片的结构直方图 #!/usr/bin/python3.4 #-*-coding:utf-8-*- #From:https://zhuanlan.zhihu.com/p/24222942 #该知乎栏目为py2编写,这里改造成py3 im=Image.open("../jpg/captcha.gif") his=im.histogram()复制打印结果为 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,1,0,0,2,0,0,0,0,1,0,0,0,0,0,2,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0

  • ubuntu 安装 jdk8

    1.下载jdk进入当前用户目录 cd~ 创建soft文件夹 mkdirsoft 下载jdk wgethttp://upyun.qubianzhong.cn/file/java/jdk-8u191-linux-x64.tar.gz 2.解压缩tar-zxvfjdk-8u191-linux-x64.tar.gz复制3.修改环境变量打开环境变量文件 sudovim~/.bashrc 在文件最后添加jdk的配置 #javajdkexportJAVA_HOME=~/soft/jdk1.8.0_191exportJRE_HOME=${JAVA_HOME}/jreexportCLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/libexportPATH=${JAVA_HOME}/bin:$PATH 编辑结束后,:wq进行保存退出 使环境变量生效 source~/.bashrc 如果报错: -bash:export:`  ':notavalididentifier 则检查~/.bashrc文件中哪里包含了空格,删除就好了。 4.测试jdkjava-version

  • 一牛逼哥们的IT公司面试及离职感受

    毕业后几年一直待在广州,觉得这是一个比较生活化及务实的城市,其互联网公司和相应的投融资环境都不如北深上活跃,大大小小的面试也有几十个,有点规模的公司应该都面试过了,面试一般会见到主力技术人员,技术主管,技术总监,人力几个人,狭义上还是可以看出一些公司文化技术氛围滴,于是想写这样一篇文章,介绍经历也给予朋友们看看。先介绍下自己的技术背景,二流大学计科毕业,GPA3.21/4.0,计算机专业课都有90分以上,高数基础不太好,也是我目前的瓶颈,程序语言基础不算差,外企,国企,民企都混过,做了6年的Android了,有3年是音视频和显示系统(Framework和Kernel),到门槛了。有3年是App方面,有几个千万月活的产品主程序经历,也是GooglePlay的顶尖开发者,随着泡沫入门了。另外也熟悉IOS和NodeJS,会写一些简单的前端,算个二吊子的全栈开发。所以,我真的只是个不算太差的三四流程序员,交待完背景,开始正文,下文涉及的公司主要有:甲骨文数据公司,三星通信研究院、腾讯;阿里巴巴、网易公司、欢聚时代、唯品会、猎豹移动;卓望公司、4399游戏、爱拍、PP金融、酷狗音乐、TCL多媒体

  • Linux云计算岗位面试时最常遇到的40个问题

    1)使用云计算有哪些优点?使用云计算有下列优点:a)备份数据和存储数据 b)强大的服务器功能 c)SaaS(软件即服务) d)信息技术沙盒功能 e)提高生产力 f)具有成本效益,并节省时间2)可否列举哪些平台用于大规模云计算?用于大规模云计算的平台包括:a)ApacheHadoop b)MapReduce3)可否解释用于云计算部署的不同模式?不同的云计算部署模式包括:a)私有云 b)公共云 c)社区云 d)混合云4)云计算与移动计算有何区别?移动计算使用与云计算同样的概念。借助互联网而不是借助单个设备,云计算因数据而变得活跃。它为用户提供了需要按需获取的数据。在移动计算中,应用程序在远程服务器上运行,为用户提供了访问所存储数据的权限。5)用户如何得益于公用计算(utilitycomputing)?公用计算让用户可以只需要为使用的资源付费。它是由决定从云端部署哪种类型的服务的企业组织管理的一种插件。大多数企业组织青睐混合策略。6)由于数据在云端传输,你如何确保数据安全?数据从一个地方传输到另一地方的过程中想确保数据安全,就要确保针对你发送的数据所使用的加密密钥没有泄露。7)云在安全方面的

  • 【学习】如何对互联网企业做基本面分析?

    对于如何对最近火热的TMT产业进行估值和分析的问题,在此推荐大家看看下面这则短文,该文由德克萨斯大学会计学博士长江商学院会计学助理教授张维宁撰写。 首先,讨论一下互联网生态的问题,每天大家都看到很多关于互联网生态的观点和评论,我今天跟大家分享一些我所理解的互联网生态的内在逻辑。以交易为核心▼首先,如何达成“交易”是整个生态的核心。换言之,所有的生态活动应该最终指向交易。2013年,这个观点争论挺大的,当时很多人都认为,互联网是流量为王,以流量为核心。但现在认可我这个观点的人越来越多了。那么,哪些是交易呢?在我的理论框架中广告不属于交易。我认为,交易可分为这三大类:实物交易、服务交易和金融交易。金融虽然也是服务的一种,但是因为金融业的盈利模式和风险控制和一般的服务很不一样,并且受到严格监管,所以我把它单列出来。1实物交易也包括两种形式:一种是线下交易,比如一家汽车制造厂商,找新浪做广告,然后指向线下卖车交易;另一种我们谈论更多的、跟互联网有关的方式是电商。2服务也分线上和线下。现已盈利的线上服务主要有两种,一种是游戏,另一种是交友或者是婚恋。线下服务就是现在最火的O2O服务。而实现交易有

  • 博弈论入门之巴什博奕

    巴什博奕巴什博奕: 两个顶尖聪明的人在玩游戏,有n个石子,每人可以随便拿1-m个石子,不能拿的人为败者,问谁会胜利 巴什博奕是博弈论问题中基础的问题它是最简单的一种情形对应一种状态的博弈博弈分析我们从最简单的情景开始分析当石子有1-m个时,毫无疑问,先手必胜当石子有m+1个时,先手无论拿几个,后手都可以拿干净,先手必败当石子有m+2-2m时,先手可以拿走几个,剩下m+1个,先手必胜我们不难发现,面临m+1个石子的人一定失败。这样的话两个人的最优策略一定是通过拿走石子,使得对方拿石子时还有m+1个我们考虑往一般情况推广设当前的石子数为n=k*(m+1)+r先手会首先拿走r个,接下来假设后手拿走x个,先手会拿走m+1-k个,这样博弈下去后手最终一定失败设当前的石子数为n=k*(m+1)假设先手拿x个,后手一定会拿m+1-x个,这样下去先手一定失败代码#include<cstdio> intmain() { intn,m; scanf("%d%d",&n,&m); if(n%(m+1)!=0)printf("firstwin"

  • Premiere Pro 2022中文版 pr 2022视频剪辑软件v22.6.2

    软件下载地址:PremierePro2022forMac(pr2022)v22.6.2激活版windows软件安装:AdobePremierePro2022(PR2022)pr2022最新版本已经上线。pr2022不仅可以帮助用户对各种视频进行剪辑、旋转、分割、合并、字幕添加、背景音乐等基础的处理,还能帮助用户进行视频颜色校正、颜色分级、稳定镜头、调整层、更改片段的持续时间和速度、效果预设等操作,功能强大。pr2022视频转字幕语言包安装说明视频字幕不能转换文字的需要单独安装补丁包视频转字幕语言包仅支持PremierePro22.3.以上,下载请谨慎下载完成后双击pkg安装包,点击继续进行安装即可。

  • 我眼中的ASP.NET Core之微服务(一)

    前言 前几天在博客园看到有园友在分享关于微软的一个微服务架构的示例程序,想必大家都已经知道了,那就是eShopOnContainers。 我们先不看项目的后缀名称OnXXX,因为除了OnContainers还有OnAzure,OnWeb,OnKubernetes以及OnServiceFabric。 我们就还是来先说说eShop这个项目吧,eShop是ASP.NETCore发布之后微软新开源出来的一个示例项目,想必大家之前也都知道微软放出来的关于Web的示例项目还有PetShop,MusicStore这两个项目。关于这两个项目我们就不做过多的介绍了,但是关于这两个项目的架构风格我们不得不提起。 PetShop:WebFrom的示例程序。典型的三层架构风格的应用程序。 MusicStore:针对于MVC3-5框架和EF的一个示例程序。无明显架构风格。 eShop:针对于ASP.NETCore的示例程序。它是一个Rest架构风格的应用程序。 我们从微软放出来的这些示例程序中也许可以看出些许东西,那就是近些年来关于架构风格的演变,或者叫微软架构风格的演变,在这里我不打算讨论关于软件架构更加深层

  • webpack入门(一)——webpack 介绍

    如今的网站正在演化为web应用程序: 1.越来越多的使用JavaScript。 2.现代浏览器提供更广泛的接口。 3.整页刷新的情况越来越少,甚至更多代码在同一个页面。(SPA) 因此有很多代码在客户端! 一个体量庞大的代码库需要好好组织。模块系统提供代码库划分成模块的选项。 模块系统风格 目前有多个标准定义依赖和输出: 1.script标签(不要模块系统) 2.CommonJS 3.AMD和它的一些变种 4.ES6 5.其它 script标签的样式 下面这种就是不用模块系统,你会怎么去管理你的代码。 <scriptsrc="module1.js"></script> <scriptsrc="module2.js"></script> <scriptsrc="libraryA.js"></script> <scriptsrc="module3.js"></script>复制 模块接口导出到全局对象,即window对象。模块的接口可以访问全局对象的依赖关系 常见问题 全局冲突 严重依赖加载

  • 【BZOJ-4212】神牛的养成计划 Trie树 + 可持久化Trie树

    4212:神牛的养成计划 TimeLimit: 10Sec  MemoryLimit: 512MBSubmit: 136  Solved: 27[Submit][Status][Discuss] Description Hzwer成功培育出神牛细胞,可最终培育出的生物体却让他大失所望...... 后来,他从某同校女神牛处知道,原来他培育的细胞发生了基因突变,原先决定神牛特征的基因序列都被破坏了,神牛hzwer很生气,但他知道基因突变的低频性,说不定还有以下优秀基因没有突变,那么他就可以用限制性核酸内切酶把它们切出来,然后再构建基因表达载体什么的,后面你懂的...... 黄学长现在知道了N个细胞的DNA序列,它们是若干个由小写字母组成的字符串。一个优秀的基因是两个字符串s1和s2,当且仅当s1是某序列的前缀的同时,s2是这个序列的后缀时,hzwer认为这个序列拥有这个优秀基因。 现在黄学长知道了M个优秀基因s1和s2,它们想知道对于给定的优秀基因,有多少个细胞的DNA序列拥有它。 Input

  • 高性能mysql的事物隔离级别

    数据库事务的隔离级别有4种,由低到高分别为Readuncommitted、Readcommitted、Repeatableread、Serializable。而且,在事务的并发操作中可能会出现脏读,不可重复读,幻读。下面通过事例一一阐述它们的概念与联系。 Readuncommitted 读未提交,顾名思义,就是一个事务可以读取另一个未提交事务的数据。 事例:老板要给程序员发工资,程序员的工资是3.6万/月。但是发工资时老板不小心按错了数字,按成3.9万/月,该钱已经打到程序员的户口,但是事务还没有提交,就在这时,程序员去查看自己这个月的工资,发现比往常多了3千元,以为涨工资了非常高兴。但是老板及时发现了不对,马上回滚差点就提交了的事务,将数字改成3.6万再提交。 分析:实际程序员这个月的工资还是3.6万,但是程序员看到的是3.9万。他看到的是老板还没提交事务时的数据。这就是脏读。 那怎么解决脏读呢?Readcommitted!读提交,能解决脏读问题。 Readcommitted 读提交,顾名思义,就是一个事务要等另一个事务提交后才能读取数据。 事例:程序员拿着信用卡去享受生活(卡里当然

  • Java里面Join(),为什么等待的是主线程,而不是当前子线程?

    1.问题描述 ​ 当我们想要一个线程插队执行的时候,我们可能会使用到thread.join();。这个会让子线程先于主线程执行完毕,然后才开始执行子线程。但是仔细一想,发现这个明明调用的是子线程的join()方法,按道理应该子线程等待执行才是,为什么反而是主线程等待了呢?相关的示例代码如下: publicstaticvoidmain(String[]args)throwsInterruptedException{ Threadthread=newThread(()->{ try{ Thread.sleep(2000L); }catch(InterruptedExceptione){ e.printStackTrace(); } System.out.println("子线程开始执行..."); }); thread.start(); thread.join(); System.out.println("主线程执行..."); } 复制 输出: 子线程开始执行... 主线程执行... 复制 2.查看源码说明 带着这个主线程等待执行的疑惑来一起看下join的源码,如下所示:

  • docker cdh(大数据工具)20220731

    1、拉取镜像dockerpullcloudera/quickstart:latest2、启动容器复制 dockerrun--privileged=true--hostname=quickstart.cloudera-p8020:8020-p7180:7180-p21050:21050-p50070:50070-p50075:50075-p50010:50010-p50020:50020-p8888:8888-t-i4239cd2958c6/usr/bin/docker-quickstart复制 3、启动cloudera-manager###/home/cloudera/cloudera-manager--force--express复制 [root@quickstart/]#/home/cloudera/cloudera-manager--enterprise&&servicentpdstart [QuickStart]ShuttingdownCDHservicesviainitscripts... kafka-server:unrecognizedservice JM

  • KVO

    //StockModel.h //KVO // //Createdby张国锋on15/7/20. //Copyright(c)2015年张国锋.Allrightsreserved. // #import<Foundation/Foundation.h> @interfaceStockModel:NSObject @property(nonatomic,strong)NSString*stockName; @property(nonatomic,strong)NSString*price; /*.....*/ @end //StockModel.m //KVO // //Createdby张国锋on15/7/20. //Copyright(c)2015年张国锋.Allrightsreserved. // #import"StockModel.h" @implementationStockModel -(void)setValue:(id)valueforUndefinedKey:(NSString*)key{ NSLog(@"UndefinedKey:%@",k

  • jetBrains 最新 lisence server

    http://180.76.140.202:9123

  • 对称矩阵的压缩存储和输出

       矩阵我个人理解就是一堆数据放在一块儿排列整齐,当然正规一点说就是m行n列的数据构成。在编程中一般采用数组对其进行存储,但矩阵中的某些特殊矩阵里,有时会出现很多数据相等或者存有很多0只有某几个位置为别的数据,那么这类矩阵我们在用数组存储的时候就会感觉比较的浪费空间,那么会对一些特殊矩阵进行压缩存储。    常见的能够压缩存储的矩阵有对称矩阵和稀疏矩阵,今天主要说说对称矩阵的压缩存储。先来说说什么是对称矩阵,相信大家都很熟悉,对于一个矩阵如果它的行和列相等并且矩阵中的数据是关于对角线对称的,那么我们称这样的矩阵为对称矩阵,拿公式来说就是:A[i][j]=A[j][i](0<=i<=N-1&&0<=j<=N-1)。            那么对于这样的对称矩阵我就只需要存储它的一个上三角或者下三角就足够,没必要对另一部分重复的数据存储。 一维数组开辟多大:   观察上面的对称矩阵,如果

相关推荐

推荐阅读