【原】Java学习笔记023 - 字符串缓冲区_正则表达式
package cn.temptation;
import java.util.Arrays;
public class Sample01 {
public static void main(String[] args) {
// 因为字符串创建后就不能修改,导致在进行字符串拼接时,会产生大量的中间字符串,创建对象都是需要消耗资源
// 所以,能不用字符串的直接拼接尽量不使用
// 字符串缓冲区:StringBuffer类/StringBuilder类
// 1、类 StringBuffer:线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但不能修改。 (线程安全)
// 2、类 StringBuilder:一个可变的字符序列。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。 (线程不安全)
// 感性认识:安全的东西常常意味着效率会较低;不安全的东西常常意味着效率会较高
// String 和 StringBuffer的区别:
// 1、String:值在创建之后不能更改,在字符串常量池中产生大量的对象,会消耗大量的资源,影响程序的效率
// 2、StringBuffer:长度和内容均可以改变,可以节省资源,提高效率
// StringBuffer:字符串缓冲区,有容量,自然理解为容器
// StringBuffer类的构造函数:
// 1、StringBuffer() :构造一个其中不带字符的字符串缓冲区,其初始容量为 16 个字符。
// 2、StringBuffer(int capacity) :构造一个不带字符,但具有指定初始容量的字符串缓冲区。
// 3、StringBuffer(String str) :构造一个字符串缓冲区,并将其内容初始化为指定的字符串内容。
// StringBuffer类的常用成员方法:
// 1、int capacity() :返回当前容量。
// 2、int length() :返回长度(字符数)。
StringBuffer sb1 = new StringBuffer();
System.out.println("sb1:" + sb1); // 无内容
System.out.println("sb1`s capacity:" + sb1.capacity()); //
System.out.println("sb1`s length:" + sb1.length()); //
System.out.println("------------------------------------------");
StringBuffer sb2 = new StringBuffer(10);
System.out.println("sb2:" + sb2); // 无内容
System.out.println("sb2`s capacity:" + sb2.capacity()); //
System.out.println("sb2`s length:" + sb2.length()); //
System.out.println("------------------------------------------");
StringBuffer sb3 = new StringBuffer("java");
System.out.println("sb3:" + sb3); // java
System.out.println("sb3`s capacity:" + sb3.capacity()); //
System.out.println("sb3`s length:" + sb3.length()); //
}
}
// 查看StringBuffer类的源码
//@Override
//public synchronized String toString() {
// if (toStringCache == null) {
// toStringCache = Arrays.copyOfRange(value, 0, count);
// }
// return new String(toStringCache, true);
//}
//
//public StringBuffer() {
// super(16);
//}
//
//public StringBuffer(int capacity) {
// super(capacity);
//}
//
//public StringBuffer(String str) {
// super(str.length() + 16);
// append(str);
//}
//@Override
//public synchronized int capacity() {
// return value.length;
//}
//
//@Override
//public synchronized int length() {
// return count;
//}
//@Override
//public synchronized StringBuffer append(String str) {
// toStringCache = null;
// super.append(str);
// return this;
//}
// 查看StringBuffer类的父类AbstractStringBuilder的源码
//char[] value;
//
//int count;
//
//AbstractStringBuilder(int capacity) {
// value = new char[capacity];
//}
//public int capacity() {
// return value.length;
//}
//@Override
//public int length() {
// return count;
//}
package cn.temptation;
public class Sample02 {
public static void main(String[] args) {
/*
* StringBuffer类的常用成员方法:(具有增加功能)
* 1、StringBuffer append(String str) :将指定的字符串追加到此字符序列。
* 2、StringBuffer insert(int offset, String str) :将字符串插入此字符序列中。
*/
StringBuffer sb = new StringBuffer();
System.out.println("sb:" + sb); // 无内容
System.out.println("sb.length():" + sb.length()); // 0
// 将指定的字符串追加到此字符序列
sb.append("java");
System.out.println("sb:" + sb); // java
System.out.println("sb.length():" + sb.length()); // 4
// 继续append
sb.append("temptation");
System.out.println("sb:" + sb); // javatemptation
System.out.println("sb.length():" + sb.length()); // 14
// 链式编程
sb.append("is").append("good");
System.out.println("sb:" + sb); // javatemptationisgood
System.out.println("sb.length():" + sb.length()); //
System.out.println("-----------------------------------------------");
StringBuffer sbTemp = new StringBuffer();
// 语法错误:The method append(Object) is ambiguous for the type StringBuffer
// sbTemp.append(null);
String strTemp = null;
sbTemp.append(strTemp);
System.out.println("sbTemp:" + sbTemp); // null
System.out.println("sbTemp.capacity():" + sbTemp.capacity()); //
System.out.println("sbTemp.length():" + sbTemp.length()); // 4
// 注意:直接把null值append给一个字符串缓冲区对象,会产生语法错误;
// null值赋值给字符串,字符串再append给一个字符串缓冲区对象,语法OK,会显示"null"字符串
System.out.println("-----------------------------------------------");
StringBuffer sb1 = new StringBuffer();
System.out.println("sb1`s capacity:" + sb1.capacity()); //
System.out.println("sb1`s length:" + sb1.length()); // 0
// 放入长度为30的字符串
// sb1.append("123456789012345678901234567890");
// System.out.println("sb1`s capacity:" + sb1.capacity()); // 34
// System.out.println("sb1`s length:" + sb1.length()); // 30
// 放入长度为40的字符串
sb1.append("1234567890123456789012345678901234567890");
System.out.println("sb1`s capacity:" + sb1.capacity()); //
System.out.println("sb1`s length:" + sb1.length()); //
System.out.println("-----------------------------------------------");
StringBuffer sb2 = new StringBuffer();
sb2.append("tom");
System.out.println("sb2:" + sb2); // sb2:tom
System.out.println("sb2`s capacity:" + sb2.capacity()); //
System.out.println("sb2`s length:" + sb2.length()); //
sb2.insert(1, "jerry");
System.out.println("sb2:" + sb2); // sb2:tjerryom
System.out.println("sb2`s capacity:" + sb2.capacity()); //
System.out.println("sb2`s length:" + sb2.length()); // 8
// 注意:理解append方法 和 insert方法,类似在食堂打菜,append方法是遵守秩序排队的,insert方法是插队的
}
}
// 查看StringBuffer类的源码
//@Override
//public synchronized StringBuffer append(String str) {
// toStringCache = null;
// super.append(str);
// return this;
//}
//
// 查看StringBuffer类的父类AbstractStringBuilder类的源码
//public AbstractStringBuilder append(String str) {
// if (str == null)
// return appendNull();
// int len = str.length(); // len:30 40
// ensureCapacityInternal(count + len); // count:0 0
// str.getChars(0, len, value, count);
// count += len;
// return this;
//}
//
//private void ensureCapacityInternal(int minimumCapacity) {
// // overflow-conscious code
// if (minimumCapacity - value.length > 0) { // minimumCapacity:30 value.length:16 minimumCapacity:40 value.length:16
// value = Arrays.copyOf(value,
// newCapacity(minimumCapacity));
// }
//}
//
// 创建StringBuffer对象的新容量方法
//private int newCapacity(int minCapacity) {
// // overflow-conscious code // minCapacity:30 minCapacity:40
// int newCapacity = (value.length << 1) + 2; // value.length << 1 相当于 value.length * 2 , newCapacity:34
// if (newCapacity - minCapacity < 0) { // 34 - 30 34 - 40
// newCapacity = minCapacity; // 30时不会走入选择结构 newCapacity:40
// }
// return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
// ? hugeCapacity(minCapacity)
// : newCapacity; // 返回newCapacity:34 返回newCapacity:40
//}
package cn.temptation;
public class Sample03 {
public static void main(String[] args) {
/*
* StringBuffer类的常用成员方法:(具有删除功能)
* 1、StringBuffer deleteCharAt(int index) :移除此序列指定位置的 char。
* 2、StringBuffer delete(int start, int end) :移除此序列的子字符串中的字符。
*/
StringBuffer sb = new StringBuffer();
sb.append("java");
System.out.println("sb:" + sb); // sb:java
System.out.println("sb.length():" + sb.length()); //
sb.deleteCharAt(2);
System.out.println("sb:" + sb); // sb:jaa
System.out.println("sb.length():" + sb.length()); //
System.out.println("----------------------------------------------------------");
sb.append("dota").append("lol");
System.out.println("sb:" + sb); // sb:jaadotalol
System.out.println("sb.length():" + sb.length()); //
sb.delete(1, 4);
System.out.println("sb:" + sb); // sb:jotalol
System.out.println("sb.length():" + sb.length()); // 7
// 移除StringBuffer对象的全部字符
// sb.delete(0, sb.length());
//
// System.out.println("sb:" + sb); // sb:
// System.out.println("sb.length():" + sb.length()); // 0
// 执行异常:String index out of range: -1
// sb.delete(-1, 2);
// 执行异常:java.lang.StringIndexOutOfBoundsException
// sb.delete(8, 10);
// 执行异常:java.lang.StringIndexOutOfBoundsException
// sb.delete(3, 2);
}
}
package cn.temptation;
public class Sample04 {
public static void main(String[] args) {
/*
* StringBuffer类的常用成员方法:(具有替换功能)
* 1、StringBuffer replace(int start, int end, String str) :使用给定 String 中的字符替换此序列的子字符串中的字符。
*/
StringBuffer sb = new StringBuffer();
sb.append("javatemptation");
System.out.println("sb:" + sb); // sb:javatemptation
// sb.replace(3, 7, "xyza");
// System.out.println("sb:" + sb); // sb:javxyzaptation
System.out.println("---------------------------------------------");
// 使用给定 String 中的字符替换此序列的子字符串中的字符。该子字符串从指定的 start 处开始,一直到索引 end - 1 处的字符,
// 如果不存在这种字符,则一直到序列尾部。
// 先将子字符串中的字符移除,然后将指定的 String 插入 start。(如果需要,序列将延长以适应指定的字符串。)
// start~end的范围小于str替换字符串的长度,在原字符串中,按start~end的范围把字符移除,再把替换字符串插入禁区,原字符串长度发生改变
sb.replace(3, 5, "xyza");
System.out.println("sb:" + sb); // sb:javxyzaemptation
System.out.println("---------------------------------------------");
// 使用给定 String 中的字符替换此序列的子字符串中的字符。该子字符串从指定的 start 处开始,一直到索引 end - 1 处的字符,
// 如果不存在这种字符,则一直到序列尾部。
// 先将子字符串中的字符移除,然后将指定的 String 插入 start。(如果需要,序列将延长以适应指定的字符串。)
// start~end的范围大于str替换字符的长度,在原字符串中,按start~end的范围把字符移除,再把替换字符串插入禁区,原字符串长度发生改变
sb.replace(3, 10, "xyza");
System.out.println("sb:" + sb); // sb:javxyzatation
}
}
package cn.temptation;
public class Sample05 {
public static void main(String[] args) {
/*
* StringBuffer类的常用成员方法:(具有反转功能)
* 1、StringBuffer reverse() :将此字符序列用其反转形式取代。
*/
String str = "abcd";
System.out.println(str);
char[] arrChar = str.toCharArray();
String result = "";
for (int i = arrChar.length - 1; i >= 0; i--) {
result += arrChar[i];
}
System.out.println(result);
System.out.println("-------------------------------------------");
StringBuffer sb = new StringBuffer();
sb.append("abcd");
System.out.println(sb);
sb.reverse();
System.out.println(sb);
}
}
package cn.temptation;
public class Sample06 {
public static void main(String[] args) {
/*
* StringBuffer类的成员方法:(具有截取功能)
* 1、String substring(int start) :返回一个新的 String,它包含此字符序列当前所包含的字符子序列。
* 2、String substring(int start, int end) :返回一个新的 String,它包含此序列当前所包含的字符子序列。
*/
StringBuffer sb = new StringBuffer();
sb.append("javatemptation");
System.out.println("sb:" + sb); // sb:javatemptation
String str1 = sb.substring(3);
System.out.println("sb:" + sb); // sb:javatemptation
System.out.println("str1:" + str1); // str1:atemptation
System.out.println("-----------------------------------------");
// 没有截取
// String str2 = sb.substring(4, 4);
// 包左不包右
String str2 = sb.substring(4, 8); // temp
// 执行异常:String index out of range: -1
// String str2 = sb.substring(4, 3);
// 执行异常:String index out of range: -4
// String str2 = sb.substring(-4, 3);
// 执行异常:java.lang.StringIndexOutOfBoundsException: String index out of range: -7
// String str2 = sb.substring(4, -3);
// 执行异常:java.lang.StringIndexOutOfBoundsException: String index out of range: -12
// String str2 = sb.substring(15, 3);
// 执行异常:java.lang.StringIndexOutOfBoundsException: String index out of range: 15
// String str2 = sb.substring(5, 15);
System.out.println("sb:" + sb); // sb:javatemptation
System.out.println("str2:" + str2);
}
}
package cn.temptation;
public class Sample07 {
public static void main(String[] args) {
// String对象 和 StringBuffer对象的互相转换
// String对象 -----> StringBuffer对象
// 方法1:使用StringBuffer类的构造函数
StringBuffer sb1 = new StringBuffer("abcd");
// 方法2:使用StringBuffer类的构造函数和append()方法
StringBuffer sb2 = new StringBuffer();
sb2.append("abcd");
System.out.println(sb1 == sb2); // false 比较的是这两个StringBuffer对象引用的地址
System.out.println(sb1.equals(sb2)); // false 追踪StringBuffer类的equals方法源码,发现其没有重写继承自Object类的equals方法
System.out.println("--------------------------------------------");
// StringBuffer对象 -----> String对象
// 方法1:使用String类的构造函数
String str1 = new String(sb1);
// 方法2:使用StringBuffer类的toString()方法
String str2 = sb1.toString();
System.out.println(str1 == str2); // false 比较的是这两个地址
System.out.println(str1.equals(str2)); // true String类重写了继承自Object类的equals方法
}
}
package cn.temptation;
import java.util.Scanner;
public class Sample08 {
public static void main(String[] args) {
// 需求:分别使用String和StringBuffer实现如下功能
// 判断字符串是否为回文字符串(对称字符串)
// 例如:回文字符串:"lol"、"BKB"、"ABBA"
String str = "";
System.out.println("输入一个字符串:");
Scanner input = new Scanner(System.in);
if (input.hasNextLine()) {
str = input.nextLine();
} else {
System.out.println("输入不正确!");
}
input.close();
// 思路1:(使用String)
// 循环比较第1个字符和最后1个字符是否相同,再比较第2个字符和倒数第2个字符是否相同...
char[] arrChar = str.toCharArray();
boolean flag = true;
// 写法1-1
// for (int i = 0, j = arrChar.length - 1; i <= j ; i++, j--) {
// // 判断相同
// if (arrChar[i] != arrChar[j]) {
// flag = false;
// break;
// }
// }
// 写法1-2
for (int i = 0; i < arrChar.length / 2; i++) {
// 判断相同
if (arrChar[i] != arrChar[arrChar.length - i - 1]) {
flag = false;
break;
}
}
System.out.println(flag ? "字符串" + str + "是回文字符串" : "字符串" + str + "不是回文字符串");
// 思路2:(使用StringBuffer)
// 将字符串进行反转,把得到的字符串和原字符串进行比较,如果相同就是回文字符串
// 写法2-1
// StringBuffer sb = new StringBuffer(str);
//
// String result = sb.reverse().toString();
// System.out.println(result.equals(str) ? "字符串" + str + "是回文字符串" : "字符串" + str + "不是回文字符串");
// 写法2-2(链式编程)
System.out.println((new StringBuffer(str)).reverse().toString().equals(str)
? "字符串" + str + "是回文字符串"
: "字符串" + str + "不是回文字符串");
// 注意:StringBuffer对象使用reverse()方法反转后,其自身内容发生了反转
}
}
package cn.temptation;
import java.util.Scanner;
public class Sample09 {
public static void main(String[] args) {
// 需求:制作一个方法对QQ号码进行验证(验证规则:QQ长度从5位~11位,只能是数字,且首位不能是0)
// 思路:
// 1、接收键盘录入的字符串
// 2、字符串的规则的校验
String str = "";
System.out.println("输入一个QQ号码:");
Scanner input = new Scanner(System.in);
if (input.hasNextLine()) {
str = input.nextLine();
} else {
System.out.println("输入不正确!");
}
input.close();
String result = validateQQ(str) ? "是QQ号码" : "不是QQ号码";
System.out.println(result);
}
/**
* 验证QQ号码
* @param qq
* @return 验证结果
*/
public static boolean validateQQ(String qq) {
boolean flag = true;
if (qq.length() >= 5 && qq.length() <= 11) {
if (qq.charAt(0) == '0') {
// 首位字符为'0'
flag = false;
} else {
// 各个位置上都是数字的判断
for (int i = 0; i < qq.length(); i++) {
if (!(qq.charAt(i) >= '0' && qq.charAt(i) <= '9')) {
flag = false;
break;
}
}
}
} else {
// 长度不在5位~11位这个范围
flag = false;
}
return flag;
}
}
package cn.temptation;
import java.util.Scanner;
public class Sample10 {
public static void main(String[] args) {
// 因为字符串的相关操作在工作中特别普遍,所以出现一种高效但是抽象的字符串操作技巧(方法)----- 正则表达式
// 需求:制作一个方法对QQ号码进行验证(验证规则:QQ长度从5位~11位,只能是数字,且首位不能是0)
String str = "";
System.out.println("输入一个QQ号码:");
Scanner input = new Scanner(System.in);
if (input.hasNextLine()) {
str = input.nextLine();
} else {
System.out.println("输入不正确!");
}
input.close();
// 使用正则表达式
String regex = "[1-9][0-9]{4,10}";
boolean flag = str.matches(regex);
String result = flag ? "是QQ号码" : "不是QQ号码";
System.out.println(result);
}
}
package cn.temptation;
public class Sample11 {
public static void main(String[] args) {
String str1 = "door";
String regex1 = "do*r"; // * 匹配前面的子表达式零次或多次
System.out.println(str1 + ":" + str1.matches(regex1)); // true
// String str1Ex = "oper"; // 匹配为false
// String str1Ex = "dr"; // 匹配为true
String str1Ex = "dooooor"; // 匹配为true
System.out.println(str1Ex + ":" + str1Ex.matches(regex1));
System.out.println("------------------------------------------------");
String str2 = "door";
String regex2 = "do+r"; // + 匹配前面的子表达式一次或多次
System.out.println(str2 + ":" + str2.matches(regex2)); // true
// String str2Ex = "dr"; // 匹配为false
String str2Ex = "dooooor"; // 匹配为true
System.out.println(str2Ex + ":" + str2Ex.matches(regex2));
System.out.println("------------------------------------------------");
String str3 = "door";
String regex3 = "do?r"; // ? 匹配前面的子表达式零次或一次
System.out.println(str3 + ":" + str3.matches(regex3)); // false
// String str3Ex = "dr"; // 匹配为true
String str3Ex = "dor"; // 匹配为true
System.out.println(str3Ex + ":" + str3Ex.matches(regex3));
System.out.println("------------------------------------------------");
String str4 = "banana";
String regex4 = "b[an]*a"; // [] 框起来的部分作为一个整体
System.out.println(str4 + ":" + str4.matches(regex4)); // true
System.out.println("------------------------------------------------");
String str5 = "door";
String regex5 = "do{2}r"; // {n} n 是一个非负整数,匹配确定的n次
System.out.println(str5 + ":" + str5.matches(regex5)); // true
System.out.println("------------------------------------------------");
String str6 = "doooooooor";
String regex6 = "do{2,}r"; // {n,} n 是一个非负整数,至少匹配n次
System.out.println(str6 + ":" + str6.matches(regex6)); // true
System.out.println("------------------------------------------------");
String str7 = "doooooooor";
String regex7 = "do{2,9}r"; // {n,m} n 和 m 均是一个非负整数,且n <= m,最少匹配n次且最多匹配m次
System.out.println(str7 + ":" + str7.matches(regex7)); // true
}
}
【原】Java学习笔记023 - 字符串缓冲区_正则表达式的更多相关文章
- 【原】Java学习笔记022 - 字符串
package cn.temptation; public class Sample01 { public static void main(String[] args) { // 字符串 // 定义 ...
- Java学习笔记之字符串常用方法
一.String关键字一些常用方法 1.构造方法: public String(); 空构造 public String(byte[] bytes);将字节数组转成字符串 public String ...
- Java学习笔记:04面向对象-内部类_访问修饰符_final
04面向对象-内部类/访问修饰符/final 1.static的介绍 static:关键字,静态的 static的作用是用来修饰类中的成员 2.访问一个类中的某一个成员变量 方法一: _1.创建对象 ...
- Java学习笔记:03面向对象-接口_多态
1.类的概念 一堆具有共同的成员变量(属性)和成员方法(功能)对象的集合 2.接口的概念 接口是功能的集合,就是方法的集合 接口中只能定义方法,不能定义普通的成员变量 而且接口中的成员方法,必须是抽象 ...
- Java学习笔记day07_琐碎知识_水仙花数_ASCII码_冒泡排序_简单选择排序_折半查找
琐碎知识: 水仙花数, ASCII码, 冒泡排序, 简单选择排序, 折半查找 1.水仙花数 每位数的平方的和等于本身. 如100到999之间的水仙花数满足: 个位的平方+十位的平方+百位的平方 = 本 ...
- 【java学习笔记】字符串和Date的转换
String dateVal = "1992-12-06 18:34:23"; SimpleDateFormat sdf = new SimpleDateFormat(" ...
- Java学习笔记4
Java学习笔记4 1. JDK.JRE和JVM分别是什么,区别是什么? 答: ①.JDK 是整个Java的核心,包括了Java运行环境.Java工具和Java基础类库. ②.JRE(Java Run ...
- java学习笔记06--正则表达式
java学习笔记06--正则表达式 正则表达式可以方便的对数据进行匹配,可以执行更加复杂的字符串验证.拆分.替换等操作. 例如:现在要去判断一个字符串是否由数字组成,则可以有以下的两种做法 不使用正则 ...
- java学习笔记16--I/O流和文件
本文地址:http://www.cnblogs.com/archimedes/p/java-study-note16.html,转载请注明源地址. IO(Input Output)流 IO流用来处理 ...
随机推荐
- Markdown语法及html内嵌
目录 1.Markdown介绍 2.Markdown语法介绍 3.内嵌html语法 之前看到很多大佬博客写的特别漂亮,非常羡慕,他们是怎么排版的呢?作为一个小白,学习使我快乐....终于在不断摸索 ...
- idea设置代码颜色主题(同Sublime Text 3的代码颜色一样)
1.下载主题的网址:http://color-themes.com,主题种类多,总有适合你的主题.在这个网址下载的主题是jar文件,直接导入,如下图file->import Setting,找 ...
- Mysql篇--Linux中安装Mysql
一.前述 由于Windows安装Mysql非常麻烦,所以分享一篇Linux中对MySQL的搭建,废话不多说,来,come on. 二.步骤 2.1 yum安装 yum install mysql-se ...
- windows之桌面程序引导功能
经常使用windows系统的同学可能都会遇到这样一种情况,刚按照完的应用程序,可能会在桌面产生一个提示信息,指示当前快捷方式可以使用了,并给出相应的文字说明,指示该快捷方式的功能.那么大家有没有考虑过 ...
- Python爬虫入门教程 22-100 CSDN学院课程数据抓取
1. CSDN学院课程数据-写在前面 今天又要抓取一个网站了,选择恐惧症使得我不知道该拿谁下手,找来找去,算了,还是抓取CSDN学院吧,CSDN学院的网站为 https://edu.csdn.net/ ...
- SpringMVC学习笔记之二(SpringMVC高级参数绑定)
一.高级参数绑定 1.1 绑定数组 需求:在商品列表页面选中多个商品,然后删除. 需求分析:功能要求商品列表页面中的每个商品前有一个checkbok,选中多个商品后点击删除按钮把商品id传递给Cont ...
- SpringMVC学习笔记之一(SpringMVC架构及与Mybatis整合)
一.SpringMVC入门 1.1Springmvc是什么 Spring web mvc和Struts2都属于表现层的框架,它是Spring框架的一部分,我们可以从Spring的整体结构中看得出来,如 ...
- Flask入门第三天
一.数据库操作 1,orm orm(object-Relation Mapping),对象-关系映射,主要实现模型对象到关系数据库数据的映射. 优点: - 只需要面向对象编程, 不需要面向数据库编写代 ...
- webpack4.0各个击破(5)—— Module篇
webpack4.0各个击破(5)-- Module篇 webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高.本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决 ...
- express中间件系统的基本实现
一直觉得express的中间件系统这种流式处理非常形象,就好像加工流水线一样,每个环节都在针对同一个产品的不同部分完成自己的工作,最后得到一个成品.今天就来实现一个简易的[中间件队列]. 一. API ...