diff --git a/.DS_Store b/.DS_Store index 99a338c..714766f 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e7e8552 --- /dev/null +++ b/.gitignore @@ -0,0 +1,23 @@ + +JVM/虚拟机执行子系统/.DS_Store +Utils/jdk8新特性/stream/.DS_Store +Utils/jdk8新特性/lambda/lambda_demo/lambda_demo.iml +Utils/jdk8新特性/lambda/lambda_demo/.idea/workspace.xml +Utils/jdk8新特性/.DS_Store +JVM/虚拟机执行子系统/.DS_Store +Utils/.DS_Store +Utils/jdk8新特性/lambda/lambda_demo/.idea/$CACHE_FILE$ +*.class +Algorithm/LeetCode/leetcode/.idea/workspace.xml +Algorithm/LeetCode/leetcode/.idea/workspace.xml +SourceCode/.DS_Store +SourceCode/mybatis/mybatis怎么加载进spring的/.DS_Store +SourceCode/mybatis/mybatis怎么加载进spring的/img/.DS_Store +SourceCode/TreeMap/.DS_Store +spring/ioc/.DS_Store +spring/aop/JDK和CGlib动态代理/img/.DS_Store +spring/aop/JDK和CGlib动态代理/.DS_Store +spring/ioc/bean的初始化/.DS_Store +spring/.DS_Store +spring/aop/.DS_Store +spring/.DS_Store diff --git a/Algorithm/.DS_Store b/Algorithm/.DS_Store index c9651a1..5b96121 100644 Binary files a/Algorithm/.DS_Store and b/Algorithm/.DS_Store differ diff --git a/Algorithm/README.md b/Algorithm/README.md new file mode 100644 index 0000000..2adb555 --- /dev/null +++ b/Algorithm/README.md @@ -0,0 +1,74 @@ +# 前言 + +大家应该都知道算法的重要性,不管是大厂小厂都非常重视,因为这个不仅考察你的逻辑能力,还有对数据结构的了解程度,还有各个集合类是否熟练 + +这一部分就是 算法的章节。 + +主要是 **剑指offer** 和 **LeetCode**上面的算法题进行整理 + +**剑指offer因为是C语言版,这里改成Java版本** + + + +这两个主要是之前自己刷题的时候写下来的,然后顺便传到GitHub上,对你们可能也有些帮助 + + + +# 先看哪个 + +**针对不同时间,侧重点也会不同** + +- 如果你时间多(离面试还有3月以上) + - 刷Leetcode +- 如果马上就要校招、社招了。刷剑指Offer。 + + + +# 格式 + +![](img/Xnip2019-11-06_22-42-30.jpg) + +## 类名 + +- 题号+类名 + +## 文档注释 + +- **主类最上面是整个问题的描述**以及我对这个题目的**审题**和**解题思路** +- 里面的静态方法是各个**不同的解题的方法**。会有**解题思路**+**时间空间复杂度** +- 也会有我对这个**现有题目进行拓展**的一些想法和**解题思路**,比如下图所示 + +针对该题目,进行一些发散性思考。(不一定是最优的,但是思考很重要) + +![](img/Xnip2019-11-06_22-49-50.jpg) + +# 剑指Offer + +很多公司,非大厂(大厂自己会改题)都从这个里面找算法题,你会看到很多校招的算法题90%都是在这本书里,所以如果你时间不多,可以突击刷这个 + + + +# LeetCode + +分为简单和中等,因为大厂的算法一般也就是中等难度,很多算法都是在中等(算法岗除外) + +每个题都是通过了测试,但是代码的风格质量可能不是最优的 + +总共就一个项目,项目分类按照包分类,分为 + +- 简单 + - 数组 + - 链表 + - 哈希 + - 二叉树 + - 等.. +- 中等 + +因为题目不可能是孤立的(比如一个题可能同时要用到数组和hash),所以只是大致分了下,我用什么标签搜索的就放进了哪个包 + +每一个类就是一个题目,每个类中的注释都会有 + +- 题目描述 +- 示例 +- 思路 +- 代码 \ No newline at end of file diff --git a/Algorithm/img/Xnip2019-11-06_22-42-30.jpg b/Algorithm/img/Xnip2019-11-06_22-42-30.jpg new file mode 100644 index 0000000..6c0983f Binary files /dev/null and b/Algorithm/img/Xnip2019-11-06_22-42-30.jpg differ diff --git a/Algorithm/img/Xnip2019-11-06_22-49-50.jpg b/Algorithm/img/Xnip2019-11-06_22-49-50.jpg new file mode 100644 index 0000000..47a5d7a Binary files /dev/null and b/Algorithm/img/Xnip2019-11-06_22-49-50.jpg differ diff --git a/Algorithm/java/KMP/.idea/workspace.xml b/Algorithm/java/KMP/.idea/workspace.xml deleted file mode 100644 index a94b281..0000000 --- a/Algorithm/java/KMP/.idea/workspace.xml +++ /dev/null @@ -1,290 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - true - DEFINITION_ORDER - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1556280699431 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1.8 - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Algorithm/java/LeetCode/leetcode/LeetCode.iml b/Algorithm/java/LeetCode/leetcode/LeetCode.iml deleted file mode 100644 index c90834f..0000000 --- a/Algorithm/java/LeetCode/leetcode/LeetCode.iml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/Algorithm/java/LeetCode/leetcode/out/production/LeetCode/easy/array/_121_BestTimeToBuyAndSellStock.class b/Algorithm/java/LeetCode/leetcode/out/production/LeetCode/easy/array/_121_BestTimeToBuyAndSellStock.class deleted file mode 100644 index 52e27e9..0000000 Binary files a/Algorithm/java/LeetCode/leetcode/out/production/LeetCode/easy/array/_121_BestTimeToBuyAndSellStock.class and /dev/null differ diff --git a/Algorithm/java/LeetCode/leetcode/src/easy/array/_121_BestTimeToBuyAndSellStock.java b/Algorithm/java/LeetCode/leetcode/src/easy/array/_121_BestTimeToBuyAndSellStock.java deleted file mode 100644 index 2b241d6..0000000 --- a/Algorithm/java/LeetCode/leetcode/src/easy/array/_121_BestTimeToBuyAndSellStock.java +++ /dev/null @@ -1,70 +0,0 @@ -package easy.array; - -/** - *描述 : 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。 - * 如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。 - * 注意你不能在买入股票前卖出股票。 - * - *示例1: 输入: [7,1,5,3,6,4] - * 输出: 5 - * 解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。 - * 注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。 - * - *示例2 输入: [7,6,4,3,1] - * 输出: 0 - * 解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。 - */ - -public class _121_BestTimeToBuyAndSellStock { - - /** - * - * 直接暴力求解,遍历两次数组,求出最优解 - */ - - public static int violence(int[] prices){ - if(prices == null || prices.length ==0){ - return 0; - } - int maxProfit = 0; - for (int i = 0; i < prices.length; i++) { - for (int j = i+1; j < prices.length; j++) { - if(prices[j]-prices[i] >maxProfit){ - maxProfit = prices[j]-prices[i]; - } - - } - } - return maxProfit; - } - - - /** - * 动态规划: - * 1.定义一个从最开始到当前位置的最小值 - * 2.计算今天减去最小值的值,也就是当天的利润 - * 3.比较当天的利润和之前的最大利润 - */ - public static int dp(int[] prices){ - if(prices == null || prices.length == 0) - return 0; - - int mixProfit = Integer.MAX_VALUE; - int maxProfit = 0; - - for (int i = 0; i < prices.length; i++) { - //找到最小值 - mixProfit = Math.min(mixProfit,prices[i]); - //比较当天的利润和最大利润 - maxProfit = Math.max(maxProfit,(prices[i]-mixProfit)); - - } - return maxProfit; - - } - - public static void main(String[] args) { - int a[] ={7,6,4,3,1}; - System.out.println(violence(a) == dp(a)); - } -} diff --git a/Algorithm/java/LeetCode/leetcode/src/easy/array/_122_BestTimeToBuyAndSellStock2.java b/Algorithm/java/LeetCode/leetcode/src/easy/array/_122_BestTimeToBuyAndSellStock2.java deleted file mode 100644 index b67c493..0000000 --- a/Algorithm/java/LeetCode/leetcode/src/easy/array/_122_BestTimeToBuyAndSellStock2.java +++ /dev/null @@ -1,43 +0,0 @@ -package easy.array; - -/** - * 描述: 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。 - * 设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。 - * 注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。 - * - * 示例1: 输入: [7,1,5,3,6,4] - * 输出: 7 - * 解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。 - * 随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。 - * 示例2: 输入: [1,2,3,4,5] - * 输出: 4 - * 解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。 - * 注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。 - * 因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。 - * - * 思路:使用两个变量 一个valley表示当天天数中最低价, - * 一个peek表示当前所有的天数中的最高价 - * 因为我们可以买卖股票且是不用付手续费的,也就是我们可以卖了这一只股票,然后再把它买回来 - * 所以上面示例2中,5-1和 (2-1)+(3-2)+(4-3)+(5-4)的效果是一样的,所以顶峰就找递增的,底就找递减的 - * - */ -public class _122_BestTimeToBuyAndSellStock2 { - public int maxProfit(int[] prices) { - if(prices.length == 0 || prices == null) - return 0; - int valley = prices[0],peek = prices[0]; - int i =0; - int maxProfit = 0; - while(i < prices.length-1){ - while(i=prices[i+1]) - i++; - valley = prices[i]; - while(i - - - - - - - \ No newline at end of file diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/count1InNum/.idea/workspace.xml" "b/Algorithm/java/\345\211\221\346\214\207offer/count1InNum/.idea/workspace.xml" deleted file mode 100644 index 27ab849..0000000 --- "a/Algorithm/java/\345\211\221\346\214\207offer/count1InNum/.idea/workspace.xml" +++ /dev/null @@ -1,286 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - - true - true - - - true - DEFINITION_ORDER - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1549599588335 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1.8 - - - - - - - - - - - - - - - \ No newline at end of file diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/countPow/countPow.iml" "b/Algorithm/java/\345\211\221\346\214\207offer/countPow/countPow.iml" deleted file mode 100644 index c90834f..0000000 --- "a/Algorithm/java/\345\211\221\346\214\207offer/countPow/countPow.iml" +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/countPow/out/production/countPow/Main.class" "b/Algorithm/java/\345\211\221\346\214\207offer/countPow/out/production/countPow/Main.class" deleted file mode 100644 index e3515c6..0000000 Binary files "a/Algorithm/java/\345\211\221\346\214\207offer/countPow/out/production/countPow/Main.class" and /dev/null differ diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/countPow/src/Main.java" "b/Algorithm/java/\345\211\221\346\214\207offer/countPow/src/Main.java" deleted file mode 100644 index fcb868c..0000000 --- "a/Algorithm/java/\345\211\221\346\214\207offer/countPow/src/Main.java" +++ /dev/null @@ -1,28 +0,0 @@ -/** - * 计算一个数的乘方 - */ - -public class Main { - - public static void main(String[] args) { - System.out.println(solution(3,3)); - - } - - - public static int solution(int base,int exponent){ - - int result=0; - if(exponent==0) - return 1; - if (exponent==1) - return base; - - result=solution(base,exponent>>1); - result*=result; - if(exponent%2==1){ - result*=base; - } - return result; - } -} diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/fibonacci/.idea/compiler.xml" "b/Algorithm/java/\345\211\221\346\214\207offer/fibonacci/.idea/compiler.xml" deleted file mode 100644 index 217af47..0000000 --- "a/Algorithm/java/\345\211\221\346\214\207offer/fibonacci/.idea/compiler.xml" +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/fibonacci/.idea/description.html" "b/Algorithm/java/\345\211\221\346\214\207offer/fibonacci/.idea/description.html" deleted file mode 100644 index db5f129..0000000 --- "a/Algorithm/java/\345\211\221\346\214\207offer/fibonacci/.idea/description.html" +++ /dev/null @@ -1 +0,0 @@ -Simple Java application that includes a class with main() method \ No newline at end of file diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/fibonacci/.idea/encodings.xml" "b/Algorithm/java/\345\211\221\346\214\207offer/fibonacci/.idea/encodings.xml" deleted file mode 100644 index e206d70..0000000 --- "a/Algorithm/java/\345\211\221\346\214\207offer/fibonacci/.idea/encodings.xml" +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/fibonacci/.idea/misc.xml" "b/Algorithm/java/\345\211\221\346\214\207offer/fibonacci/.idea/misc.xml" deleted file mode 100644 index de8f7c7..0000000 --- "a/Algorithm/java/\345\211\221\346\214\207offer/fibonacci/.idea/misc.xml" +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/fibonacci/.idea/modules.xml" "b/Algorithm/java/\345\211\221\346\214\207offer/fibonacci/.idea/modules.xml" deleted file mode 100644 index 59c3b94..0000000 --- "a/Algorithm/java/\345\211\221\346\214\207offer/fibonacci/.idea/modules.xml" +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/fibonacci/.idea/workspace.xml" "b/Algorithm/java/\345\211\221\346\214\207offer/fibonacci/.idea/workspace.xml" deleted file mode 100644 index f88ac4f..0000000 --- "a/Algorithm/java/\345\211\221\346\214\207offer/fibonacci/.idea/workspace.xml" +++ /dev/null @@ -1,168 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - true - DEFINITION_ORDER - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1552104752438 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1.8 - - - - - - - - - - - - - - - \ No newline at end of file diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/out/production/singletonDemo/HungerSingleton.class" "b/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/out/production/singletonDemo/HungerSingleton.class" deleted file mode 100644 index 462be04..0000000 Binary files "a/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/out/production/singletonDemo/HungerSingleton.class" and /dev/null differ diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/out/production/singletonDemo/HungerSingletonStatic.class" "b/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/out/production/singletonDemo/HungerSingletonStatic.class" deleted file mode 100644 index 62b796a..0000000 Binary files "a/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/out/production/singletonDemo/HungerSingletonStatic.class" and /dev/null differ diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/out/production/singletonDemo/LazySingleton.class" "b/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/out/production/singletonDemo/LazySingleton.class" deleted file mode 100644 index 0c0548f..0000000 Binary files "a/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/out/production/singletonDemo/LazySingleton.class" and /dev/null differ diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/out/production/singletonDemo/LazySingletonSecurity.class" "b/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/out/production/singletonDemo/LazySingletonSecurity.class" deleted file mode 100644 index 1335642..0000000 Binary files "a/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/out/production/singletonDemo/LazySingletonSecurity.class" and /dev/null differ diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/out/production/singletonDemo/Main.class" "b/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/out/production/singletonDemo/Main.class" deleted file mode 100644 index 79199e8..0000000 Binary files "a/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/out/production/singletonDemo/Main.class" and /dev/null differ diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/out/production/singletonDemo/Person.class" "b/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/out/production/singletonDemo/Person.class" deleted file mode 100644 index b4d77c6..0000000 Binary files "a/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/out/production/singletonDemo/Person.class" and /dev/null differ diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/singletonDemo.iml" "b/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/singletonDemo.iml" deleted file mode 100644 index c90834f..0000000 --- "a/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/singletonDemo.iml" +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/src/HungerSingleton.java" "b/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/src/HungerSingleton.java" deleted file mode 100644 index 6c9a885..0000000 --- "a/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/src/HungerSingleton.java" +++ /dev/null @@ -1,35 +0,0 @@ -/** - * 饿汉式,线程安全 - * 缺点:浪费内存资源 - */ - -public class HungerSingleton { - - // 构造方法私有 - private HungerSingleton(){ - - } - - private final static HungerSingleton instance = new HungerSingleton(); - - // 对外提供方法 - public static HungerSingleton getInstance(){ - return instance; - } -} - -class HungerSingletonStatic{ - - private static HungerSingletonStatic instance; - private HungerSingletonStatic(){ - - } - - static { - instance = new HungerSingletonStatic(); - } - - public static HungerSingletonStatic getInstance() { - return instance; - } -} diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/src/LazySingleton.java" "b/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/src/LazySingleton.java" deleted file mode 100644 index 718ce71..0000000 --- "a/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/src/LazySingleton.java" +++ /dev/null @@ -1,42 +0,0 @@ -/** - * 懒汉式: - * 优点:用到的时候才添加 - * 缺点:线程不安全,当两个线程同时调用的时候,会创建两个实例 - */ - -public class LazySingleton { - private static LazySingleton instance; - private LazySingleton(){ - - } - - public static LazySingleton getInstance() { - if (instance == null) { - instance = new LazySingleton(); - } - return instance; - } -} - - -/** - * 懒汉式 - * 双重锁确保线程安全,同时又提升了性能 - */ -class LazySingletonSecurity{ - private static LazySingletonSecurity instance1; - private LazySingletonSecurity(){ - - } - - public static LazySingletonSecurity getInstance1() { - if (instance1 == null) { - synchronized (LazySingletonSecurity.class){ - if (instance1 == null) { - instance1 = new LazySingletonSecurity(); - } - } - } - return instance1; - } -} \ No newline at end of file diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/src/Main.java" "b/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/src/Main.java" deleted file mode 100644 index 3e6121c..0000000 --- "a/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/src/Main.java" +++ /dev/null @@ -1,11 +0,0 @@ -public class Main { - public static void main(String[] args) { - - Person p = new Person("张三", 19); - String s="sdaf "; - System.out.println(p.toString()); - System.out.println(s); - - } -} - diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/src/Person.java" "b/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/src/Person.java" deleted file mode 100644 index ff7a0c7..0000000 --- "a/Algorithm/java/\345\211\221\346\214\207offer/singletonDemo/src/Person.java" +++ /dev/null @@ -1,34 +0,0 @@ -public class Person { - private String name; - private int age; - - - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public int getAge() { - return age; - } - - public void setAge(int age) { - this.age = age; - } - - public Person(String name, int age) { - - this.name = name; - this.age = age; - } - - public Person() { - - } -} - - diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/symmertricalTree/.idea/compiler.xml" "b/Algorithm/java/\345\211\221\346\214\207offer/symmertricalTree/.idea/compiler.xml" deleted file mode 100644 index a1757ae..0000000 --- "a/Algorithm/java/\345\211\221\346\214\207offer/symmertricalTree/.idea/compiler.xml" +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/symmertricalTree/.idea/misc.xml" "b/Algorithm/java/\345\211\221\346\214\207offer/symmertricalTree/.idea/misc.xml" deleted file mode 100644 index fa53a49..0000000 --- "a/Algorithm/java/\345\211\221\346\214\207offer/symmertricalTree/.idea/misc.xml" +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/treeToList/.idea/compiler.xml" "b/Algorithm/java/\345\211\221\346\214\207offer/treeToList/.idea/compiler.xml" deleted file mode 100644 index a1757ae..0000000 --- "a/Algorithm/java/\345\211\221\346\214\207offer/treeToList/.idea/compiler.xml" +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/treeToList/.idea/misc.xml" "b/Algorithm/java/\345\211\221\346\214\207offer/treeToList/.idea/misc.xml" deleted file mode 100644 index fa53a49..0000000 --- "a/Algorithm/java/\345\211\221\346\214\207offer/treeToList/.idea/misc.xml" +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/verifySquenceOfBST/.idea/compiler.xml" "b/Algorithm/java/\345\211\221\346\214\207offer/verifySquenceOfBST/.idea/compiler.xml" deleted file mode 100644 index a1757ae..0000000 --- "a/Algorithm/java/\345\211\221\346\214\207offer/verifySquenceOfBST/.idea/compiler.xml" +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/verifySquenceOfBST/.idea/misc.xml" "b/Algorithm/java/\345\211\221\346\214\207offer/verifySquenceOfBST/.idea/misc.xml" deleted file mode 100644 index fa53a49..0000000 --- "a/Algorithm/java/\345\211\221\346\214\207offer/verifySquenceOfBST/.idea/misc.xml" +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git "a/Algorithm/java/\346\236\201\345\256\242\346\227\266\351\227\264-\345\267\246\347\245\236\347\256\227\346\263\225/sort/.idea/compiler.xml" "b/Algorithm/java/\346\236\201\345\256\242\346\227\266\351\227\264-\345\267\246\347\245\236\347\256\227\346\263\225/sort/.idea/compiler.xml" deleted file mode 100644 index a1757ae..0000000 --- "a/Algorithm/java/\346\236\201\345\256\242\346\227\266\351\227\264-\345\267\246\347\245\236\347\256\227\346\263\225/sort/.idea/compiler.xml" +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git "a/Algorithm/java/\346\236\201\345\256\242\346\227\266\351\227\264-\345\267\246\347\245\236\347\256\227\346\263\225/sort/.idea/misc.xml" "b/Algorithm/java/\346\236\201\345\256\242\346\227\266\351\227\264-\345\267\246\347\245\236\347\256\227\346\263\225/sort/.idea/misc.xml" deleted file mode 100644 index fa53a49..0000000 --- "a/Algorithm/java/\346\236\201\345\256\242\346\227\266\351\227\264-\345\267\246\347\245\236\347\256\227\346\263\225/sort/.idea/misc.xml" +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git "a/Algorithm/java/\346\236\201\345\256\242\346\227\266\351\227\264-\345\267\246\347\245\236\347\256\227\346\263\225/sort/.idea/modules.xml" "b/Algorithm/java/\346\236\201\345\256\242\346\227\266\351\227\264-\345\267\246\347\245\236\347\256\227\346\263\225/sort/.idea/modules.xml" deleted file mode 100644 index cdfa7d1..0000000 --- "a/Algorithm/java/\346\236\201\345\256\242\346\227\266\351\227\264-\345\267\246\347\245\236\347\256\227\346\263\225/sort/.idea/modules.xml" +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git "a/Algorithm/java/\346\236\201\345\256\242\346\227\266\351\227\264-\345\267\246\347\245\236\347\256\227\346\263\225/sort/.idea/workspace.xml" "b/Algorithm/java/\346\236\201\345\256\242\346\227\266\351\227\264-\345\267\246\347\245\236\347\256\227\346\263\225/sort/.idea/workspace.xml" deleted file mode 100644 index cb91897..0000000 --- "a/Algorithm/java/\346\236\201\345\256\242\346\227\266\351\227\264-\345\267\246\347\245\236\347\256\227\346\263\225/sort/.idea/workspace.xml" +++ /dev/null @@ -1,284 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - - true - true - - - true - DEFINITION_ORDER - - - - - - - - - - - - - - - - - - - - - - - @@ -171,6 +268,9 @@ + + + @@ -217,12 +317,12 @@ - @@ -243,8 +343,8 @@ - - + + @@ -264,27 +364,106 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -293,10 +472,10 @@ - + - - + + diff --git a/Struct/README.md b/Struct/README.md new file mode 100644 index 0000000..7d8c51e --- /dev/null +++ b/Struct/README.md @@ -0,0 +1,39 @@ +# 前言 + +数据结构的重要性应该不用说,可以说你能完整的写一个数据结构,可能才算入门。如果真的写一个可以接近推广的数据结构,你就基本很牛逼了 + +我这个只是第一版,没有用到 泛型,各种接口, transient关键字 + + + +只是想简单的实现几个功能,让你了解一下这个数据结构是怎么实现的,命名也接近源码的命名,可能有些不太一样 + + + +后期会慢慢迭代出很多版本,这个适合入门的时候看 + + + +# 有什么数据结构 + +- HashMap +- ArrayList +- LinkedList + +# 配套的文章 + +## HashMap + +- [hashMap 部分源码注释]() +- [HashMap-put过程](https://github.com/leosanqing/Java-Notes/blob/master/hashMap/HashMap%E5%88%86%E6%9E%90.md) +- [HashMap 输入初始值时,table 长度](https://github.com/leosanqing/Java-Notes/blob/master/hashMap/table%E9%95%BF%E5%BA%A6%E5%88%B0%E5%BA%95%E6%98%AF%E5%A4%9A%E5%B0%91.md) +- [为啥HashMap的长度一定是2的n次方](https://github.com/leosanqing/Java-Notes/blob/master/hashMap/%E4%B8%BA%E5%95%A5HashMap%E7%9A%84%E9%95%BF%E5%BA%A6%E4%B8%80%E5%AE%9A%E6%98%AF2%E7%9A%84n%E6%AC%A1%E6%96%B9.md) + +## LinkedList + + + +## ArrayList + +- 为什么 设置数组最大值的时候要 -8 +- fastMove的步骤 \ No newline at end of file diff --git a/Struct/src/com/leosanqing/arrayList/ArrayListV1.java b/Struct/src/com/leosanqing/arrayList/ArrayListV1.java new file mode 100644 index 0000000..28f8ca4 --- /dev/null +++ b/Struct/src/com/leosanqing/arrayList/ArrayListV1.java @@ -0,0 +1,284 @@ +package com.leosanqing.arrayList; + +import java.util.Arrays; + +/** + * ArrayList version 版本 不使用 泛型 + *

+ * 只有简单的增删改查功能,还有一些基础的 + */ + +public class ArrayListV1 { + private int size = 0; + private static final int DEFAULT_CAPACITY = 10; + private static Object[] EMPTY_ELEMENTDATA = {}; + + private int modCount = 0; + + /** + * 为啥减去8,因为需要存储数组的长度,详细的可以看我的相关文章,里面有介绍 + */ + private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; + /** + * 无参构造的时候创建的数组,为了和上面的 EMPTY_ELEMENTDATA区分 + * 以便了解我们第一次添加元素时,数组大小扩容成多大 + */ + private static Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; + + Object elementData[]; + + public ArrayListV1(int initialCapacity) { + if (initialCapacity >= 0) { + elementData = new Object[initialCapacity]; + } else { + throw new IllegalArgumentException("不合法的数组大小: " + + initialCapacity); + } + } + + public ArrayListV1(int size, Object[] elementData) { + this.size = size; + this.elementData = elementData; + } + + public ArrayListV1() { + this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; + } + + public int size() { + return size; + } + + + public boolean isEmpty() { + return size == 0; + } + + + /** + * 是否包含这个元素,是,返回true,否则返回false + * @param o + * @return + */ + public boolean contains(Object o) { + return indexOf(0) >= 0; + } + + /** + * 根据对象来找出最早出现的索引 + *

+ * 如果没找到,返回 -1 + */ + public int indexOf(Object o) { + if (o == null) { + for (int i = 0; i < size; i++) { + if (elementData[i] == null) + return i; + } + } else { + for (int i = 0; i < size; i++) { + if (elementData[i].equals(o)) + return i; + } + } + return -1; + } + + /** + * 根据对象找出最后一次对象出现的索引 + *

+ * 如果没有匹配到,返回-1 + * + * @param o + * @return + */ + public int lastIndexOf(Object o) { + if (o == null) { + for (int i = size; i > 0; i--) { + if (elementData[i] == null) + return i; + } + } else { + for (int i = size; i > 0; i--) + if (o.equals(elementData[i])) + return i; + } + return -1; + } + + /** + * 将列表转成数组 + * + * @return + */ + public Object[] toArray() { + return Arrays.copyOf(elementData, size); + } + + /** + * 添加数据到数组的末尾 + * + * @param o + * @return + */ + public boolean add(Object o) { + ensureCapacityInternal(size + 1); + elementData[size++] = o; + return true; + } + + /** + * 设置第 i个位置上的数据,并返回原来的值 + * + * @param index + * @param elem + * @return + */ + public Object set(int index, Object elem) { + rangeCheck(index); + Object oldValue = elementData[index]; + elementData[index] = elem; + return oldValue; + } + + + + private void ensureCapacityInternal(int miniCapacity) { + ensureExplicitCapacity(calculateCapacity(elementData, miniCapacity)); + } + + /** + * 确认一下是否需要扩容 + * @param miniCapacity + */ + private void ensureExplicitCapacity(int miniCapacity) { + modCount++; + if (miniCapacity - elementData.length > 0) + grow(miniCapacity); + } + + /** + * 计算一下需要扩容的值,这个只有在使用无参构造的时候才会触发 + * @param elementData + * @param miniCapacity + * @return + */ + private static int calculateCapacity(Object[] elementData, int miniCapacity) { + if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) + return Math.max(DEFAULT_CAPACITY, miniCapacity); + return miniCapacity; + } + /** + * 数组扩容,扩容成1.5倍 + * + * @param miniCapacity + */ + private void grow(int miniCapacity) { + int oldCapacity = elementData.length; + int newCapacity = oldCapacity + (oldCapacity >> 1); + if (newCapacity - miniCapacity < 0) + newCapacity = miniCapacity; + if (newCapacity - MAX_ARRAY_SIZE > 0) + newCapacity = hugeCapacity(miniCapacity); + elementData = Arrays.copyOf(elementData, newCapacity); + + } + + /** + * 数组的长度非常大的时候的处理方式 + * + * @param miniCapacity + * @return + */ + private int hugeCapacity(int miniCapacity) { + if (miniCapacity < 0) + throw new OutOfMemoryError(); + return (miniCapacity > MAX_ARRAY_SIZE) ? + Integer.MAX_VALUE : MAX_ARRAY_SIZE; + } + + + + /** + * 根据索引查找元素,并返回 + * + * @param index + * @return + */ + public Object get(int index) { + rangeCheck(index); + return elementData[index]; + } + + /** + * 检查索引是否合法 + * + * @param index + */ + private void rangeCheck(int index) { + if (index < 0 || index > size) { + throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); + } + } + + private String outOfBoundsMsg(int index) { + return "输入的地址不合法: index:" + index + "size: " + size; + } + + /** + * 去掉该索引的数据,和清空不一样,清空是设置为 null,他是直接删除了该索引 + * @param index + * @return + */ + public Object remove(int index){ + rangeCheck(index); + Object oldValue = elementData[index]; + fastRemove(index); + elementData[size--] =null; + return oldValue; + } + + + /** + * 移动数组,删除操作或者整理数组的时候使用 + * @param index + */ + private void fastRemove(int index){ + modCount++; + // 需要移动的位数 + int numMove = size - index - 1; + // 把这个索引后面的所有元素复制到从这个索引开始的位置 + // 相当于直接将数组前移,覆盖掉了那个索引的数据,然后数组最后的位置设置为空即可 + if(numMove>0){ + System.arraycopy(elementData,index+1,elementData,index,numMove); + } + elementData[size--] = null; + } + + + /** + * 给定一个对象,移除第一次遇到的这个对象 + * @param object + * @return + */ + public boolean remove(Object object){ + if(object == null){ + for (int index = 0; index < size; index++) { + if(elementData[index]==null){ + fastRemove(index); + return true; + } + } + }else{ + for (int index = 0; index < size; index++) { + if(elementData[index].equals(object)){ + fastRemove(index); + return true; + } + + } + } + return false; + } + +} diff --git a/Struct/src/com/leosanqing/linkedList/LinkedList.java b/Struct/src/com/leosanqing/linkedList/LinkedListV1.java similarity index 90% rename from Struct/src/com/leosanqing/linkedList/LinkedList.java rename to Struct/src/com/leosanqing/linkedList/LinkedListV1.java index c7f8ce2..aaa365b 100644 --- a/Struct/src/com/leosanqing/linkedList/LinkedList.java +++ b/Struct/src/com/leosanqing/linkedList/LinkedListV1.java @@ -2,19 +2,19 @@ /** - * LinkedList 1.0 version + * LinkedListV1 1.0 version * * 只实现最最基础的功能,能进行增删改查操作 */ -public class LinkedList { +public class LinkedListV1 { private Node first; private Node last; // 临时变量 private Node p; private int size; - public LinkedList(){ + public LinkedListV1(){ first = new Node(); last = first; size = 0; @@ -97,6 +97,16 @@ Node node (int index){ } + /** + * 给定索引,获取节点的数据 + * @param index + * @return + */ + public Object get(int index){ + checkElemIndex(index); + return node(index).data; + } + /** * 检查是否为正确的索引,如果是,返回true;否则返回false * @param index diff --git a/Struct/src/com/leosanqing/queue/QueueV1.java b/Struct/src/com/leosanqing/queue/QueueV1.java new file mode 100644 index 0000000..d9a6c9f --- /dev/null +++ b/Struct/src/com/leosanqing/queue/QueueV1.java @@ -0,0 +1,4 @@ +package com.leosanqing.queue; + +public class QueueV1 { +} diff --git a/Utils/.DS_Store b/Utils/.DS_Store new file mode 100644 index 0000000..70d2f16 Binary files /dev/null and b/Utils/.DS_Store differ diff --git a/Utils/README.md b/Utils/README.md new file mode 100644 index 0000000..5b39e9f --- /dev/null +++ b/Utils/README.md @@ -0,0 +1,17 @@ +# 有什么 + +这里主要更一些中间件,和一些工具。(除了语言本身和spring框架之外的)。 + + + +# JDK8 新特性 + +- [lambda表达式](https://github.com/leosanqing/Java-Notes/tree/master/Utils/jdk8%E6%96%B0%E7%89%B9%E6%80%A7/lambda) +- [stream流操作](https://github.com/leosanqing/Java-Notes/tree/master/Utils/jdk8%E6%96%B0%E7%89%B9%E6%80%A7/stream) + +# Redis + +- [redis安装和配置](https://github.com/leosanqing/food-shop/tree/master/2.0/blog/redis) +- [主从复制和哨兵模式](https://github.com/leosanqing/food-shop/tree/master/2.0/blog/redis/%E9%85%8D%E7%BD%AE%E4%B8%BB%E4%BB%8E%E5%A4%8D%E5%88%B6) +- Redis集群配置(待更) + diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/.DS_Store" b/Utils/Redis/.DS_Store similarity index 100% rename from "Algorithm/java/\345\211\221\346\214\207offer/.DS_Store" rename to Utils/Redis/.DS_Store diff --git a/Utils/Redis/README.md b/Utils/Redis/README.md new file mode 100644 index 0000000..1be2822 --- /dev/null +++ b/Utils/Redis/README.md @@ -0,0 +1,70 @@ +# 安装环境 + +《Redis实战》这本书中的例子是可以运行的,学习Redis,怎么少的了 Redis的安装 。如果按照书中的代码,还要安装python2 + + + +## 安装Homebrew + +Homebrew 是MacOS 上管理软件的一个工具。 + +**如果你要安装新的版本或者安装 Redis,或者其他各种软件,可以使用 Homebrew来进行管理** + +具体 安装方法可以点击 [Homebrew安装](https://segmentfault.com/a/1190000018360813) + +## 安装Python + +我使用的 MacOS的环境,**而且跟书中的安装方式不一样**。所以如果是 Windows 或者 linux,可以看书中的步骤或者自行百度一下。 + +MacOS 自己就预安装了 Python2的。**所以可以不用安装**,你可以根据 `python --version`查看当前运行的版本 + +![](img/Xnip2019-11-17_10-33-21.jpg) + +其他命令可以参照这个来 [查看python环境相关](https://blog.csdn.net/BTUJACK/article/details/83856274) + + + +**如果想安装 python3**,而且安装了 Homebrew 可以直接使用 命令 `brew install python3` + +如果想安装 Python的依赖库,比如 scrapy,可以用 Homebrew 安装 pip3 `brew install pip3`. 然后使用 `pip3 install scrapy` + + + +## 安装Redis + +如果你已经安装了 Homebrew,可以直接 使用 `brew install redis` + +之前说了 如果使用 Homebrew 命令安装的话,他会将软件下载到 /usr/local/Cellar + +![](img/Xnip2019-11-17_10-52-02.jpg) + +我们可以进入 redis的bin下,启动他的服务器 `redis-server`(注意:**如果你按照书上的方法使用 python 写入redis出错。可能是你没有启动这个服务**) + + + +# 使用Python写入Redis + +1. 使用 `python`命令进入 python命令行 . 如果你要用 python3 ,使用 `python3`就行 + +![](img/Xnip2019-11-17_10-59-23.jpg) + +2. 按照书上的步骤,写入redis 试试 + 1. 导入依赖 `import redis`.如果这步出错,是因为没有安装 redis的依赖 + 2. 然后获取连接 `conn = redis.Redis()` 这步出错是没有启动 redis服务,可以看我上面的步骤 + 3. 设置值 `conn.set('hello','world')` + 4. 获取值 conn.get('hello') + +![](img/Xnip2019-11-17_11-37-07.jpg) + +# 如果出错 + +![](img/Xnip2019-11-17_11-03-57.jpg) + +## 因为没有安装 redis依赖 + +1. 如果没有使用Homebrew安装python3,使用的是系统自带的 python + 1. 使用 `sudo easy_install pip` 安装 pip。(相当于 Java里的Maven) + 2. 然后 pip install redis +2. 如果使用Homebrew安装的python3,先看看有没有安装 pip3。 + 1. 没有 可以使用 `brew install pip3` + 2. 然后使用 `pip3 install redis`就行了 \ No newline at end of file diff --git a/Utils/Redis/img/Xnip2019-11-17_10-33-21.jpg b/Utils/Redis/img/Xnip2019-11-17_10-33-21.jpg new file mode 100644 index 0000000..696415d Binary files /dev/null and b/Utils/Redis/img/Xnip2019-11-17_10-33-21.jpg differ diff --git a/Utils/Redis/img/Xnip2019-11-17_10-52-02.jpg b/Utils/Redis/img/Xnip2019-11-17_10-52-02.jpg new file mode 100644 index 0000000..d1abb44 Binary files /dev/null and b/Utils/Redis/img/Xnip2019-11-17_10-52-02.jpg differ diff --git a/Utils/Redis/img/Xnip2019-11-17_10-59-23.jpg b/Utils/Redis/img/Xnip2019-11-17_10-59-23.jpg new file mode 100644 index 0000000..8f3df0a Binary files /dev/null and b/Utils/Redis/img/Xnip2019-11-17_10-59-23.jpg differ diff --git a/Utils/Redis/img/Xnip2019-11-17_11-03-57.jpg b/Utils/Redis/img/Xnip2019-11-17_11-03-57.jpg new file mode 100644 index 0000000..b9e5833 Binary files /dev/null and b/Utils/Redis/img/Xnip2019-11-17_11-03-57.jpg differ diff --git a/Utils/Redis/img/Xnip2019-11-17_11-37-07.jpg b/Utils/Redis/img/Xnip2019-11-17_11-37-07.jpg new file mode 100644 index 0000000..dbdda1d Binary files /dev/null and b/Utils/Redis/img/Xnip2019-11-17_11-37-07.jpg differ diff --git a/Utils/Redis/python2/.DS_Store b/Utils/Redis/python2/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/Utils/Redis/python2/.DS_Store differ diff --git a/Utils/Redis/python2/.idea/inspectionProfiles/profiles_settings.xml b/Utils/Redis/python2/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/Utils/Redis/python2/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/Utils/Redis/python2/.idea/misc.xml b/Utils/Redis/python2/.idea/misc.xml new file mode 100644 index 0000000..060be30 --- /dev/null +++ b/Utils/Redis/python2/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git "a/Algorithm/java/\345\211\221\346\214\207offer/countPow/.idea/modules.xml" b/Utils/Redis/python2/.idea/modules.xml similarity index 59% rename from "Algorithm/java/\345\211\221\346\214\207offer/countPow/.idea/modules.xml" rename to Utils/Redis/python2/.idea/modules.xml index 2240ec6..a82d671 100644 --- "a/Algorithm/java/\345\211\221\346\214\207offer/countPow/.idea/modules.xml" +++ b/Utils/Redis/python2/.idea/modules.xml @@ -2,7 +2,7 @@ - + \ No newline at end of file diff --git a/Utils/Redis/python2/.idea/python2.iml b/Utils/Redis/python2/.idea/python2.iml new file mode 100644 index 0000000..85c7612 --- /dev/null +++ b/Utils/Redis/python2/.idea/python2.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/Utils/Redis/python2/.idea/workspace.xml b/Utils/Redis/python2/.idea/workspace.xml new file mode 100644 index 0000000..8b72154 --- /dev/null +++ b/Utils/Redis/python2/.idea/workspace.xml @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1573869588733 + + + + + + + + + + file://$PROJECT_DIR$/com/leosanqing/utilstest/cha1_vote.py + 114 + + + file://$PROJECT_DIR$/com/leosanqing/utilstest/cha1_vote.py + 125 + + + file://$PROJECT_DIR$/com/leosanqing/utilstest/cha1_vote.py + 102 + + + file://$PROJECT_DIR$/com/leosanqing/utilstest/cha1_vote.py + 21 + + + + + + + + + \ No newline at end of file diff --git a/Utils/Redis/python2/com/leosanqing/utilstest/cha1_vote.py b/Utils/Redis/python2/com/leosanqing/utilstest/cha1_vote.py new file mode 100644 index 0000000..0c98cc0 --- /dev/null +++ b/Utils/Redis/python2/com/leosanqing/utilstest/cha1_vote.py @@ -0,0 +1,155 @@ +# -*- coding:utf-8 -*- + + +""" +Redis实战的第一章的 投票的代码 +""" +import time +import unittest + +ONE_WEEK_IN_SECONDS = 7 * 86400 +VOTE_SCORE = 432 + + +def article_vote(conn, user, article): + cutoff = time.time() - ONE_WEEK_IN_SECONDS + # 超时,不能投票 + if conn.zscore('time:', article) < cutoff: + return + + article_id = article.partition(':')[-1] + # 判断是不是第一次投票 + if conn.sadd('voted:' + article_id, user): + # 改版了,需要将顺序改下,不然会报错 + # conn.zincrby('score:', article, VOTE_SCORE) + conn.zincrby('score:', VOTE_SCORE, article) + conn.hincrby(article, 'votes', 1) + + +# +def post_article(conn, user, title, link): + # 生成文章的id,使用自增 + article_id = str(conn.incr('article:')) + + voted = 'voted:' + article_id + # 将作者添加进投票的人中 + conn.sadd(voted, user) + # 设置超时时间 + conn.expire(voted, ONE_WEEK_IN_SECONDS) + now = time.time() + article = 'article:' + article_id + + # 将文件信息存储在散列里 + conn.hmset(article, { + 'title': title, + 'link': link, + 'poster': user, + 'time': now, + 'votes': 1 + }) + + mapping1 = {article: now + VOTE_SCORE} + mapping2 = {article: now} + conn.zadd('score:', mapping1) + conn.zadd('time:', mapping2) + return article_id + + +# + + +ARTICLES_PRE_PAGE = 25 + + +# 获取文章 +def get_articles(conn, page, order='score:'): + start = (page - 1) * ARTICLES_PRE_PAGE + end = start + ARTICLES_PRE_PAGE - 1 + + ids = conn.zrevrange(order, start, end) + articles = [] + for id1 in ids: + article_data = conn.hgetall(id1) + article_data['id'] = id1 + articles.append(article_data) + return articles + + +# 对文章进行分组 +def add_remove_groups(conn, article_id, to_add=[], to_remove=[]): + article = 'article:' + article_id + for group in to_add: + conn.sadd('group:' + group, article) + for group in to_remove: + conn.srem('group:' + group, article) + + +# 获取一组的文章 +def get_group_articles(conn, group, page, order='score:'): + key = order + group + if not conn.exists(key): + conn.zinterstore(key, + ['group:' + group, order], + aggregate='max', + ) + conn.expire(key, 60) + return get_articles(conn, page, key) + + +# 测试用 +class TestCh01(unittest.TestCase): + def setUp(self): + import redis + self.conn = redis.Redis(db=15) + + # def tearDown(self): + # del self.conn + # print + # print + + def test_article_functionality(self): + conn = self.conn + import pprint + + article_id = str(post_article(conn, 'username', 'A title', 'http://www.google.com')) + print("We posted a new article with id:", article_id) + print + self.assertTrue(article_id) + + print("Its HASH looks like:") + r = conn.hgetall('article:' + article_id) + print(r) + print + self.assertTrue(r) + + article_vote(conn, 'other_user', 'article:' + article_id) + print("We voted for the article, it now has votes:",) + v = int(conn.hget('article:' + article_id, 'votes')) + print(v) + print + self.assertTrue(v > 1) + + print("The currently highest-scoring articles are:") + articles = get_articles(conn, 1) + pprint.pprint(articles) + print + + self.assertTrue(len(articles) >= 1) + + add_remove_groups(conn, article_id, ['new-group']) + print "We added the article to a new group, other articles include:" + articles = get_group_articles(conn, 'new-group', 1) + pprint.pprint(articles) + print + self.assertTrue(len(articles) >= 1) + + to_del = ( + conn.keys('time:*') + conn.keys('voted:*') + conn.keys('score:*') + + conn.keys('article:*') + conn.keys('group:*') + ) + if to_del: + conn.delete(*to_del) + + +if __name__ == '__main__': + unittest.main() diff --git "a/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/README.md" "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/README.md" new file mode 100644 index 0000000..bceb463 --- /dev/null +++ "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/README.md" @@ -0,0 +1,461 @@ +# 前言 + +> 项目代码在本级目录下的**lambda_demo**中 + +说起 JDK8 的新特性,总绕不过两个,一个是**流(stream)**,一个就**是 lambda表达式。** + +因为 引入 lambda 表达式 可以说是 Java 的**一次革命性的尝试**,因为lambda表达式是**函数式编程**,把函数方法参数化。而之前的 Java 是面向对象的,非常非常严格的。甚至可以说是呆板。 + +但是 Java的之前的那种风格 或者说设定**并不能说是他的弊端**,对于刚入门编程的人或者初中级的Java编程者来说,Java的这种语法更是他的**优势**,尤其是企业级的应用来说,**易于维护和易于理解比运行效率更重要**。这也是Java最近几年被作为企业级应用程序的首选语言的原因,因为谁都不能保证和你共事的人都是顶尖的人才,你写的他都懂,他写的你都懂 + + + +但是,随着软件的发展,会编程的人越来越多,门槛不断升高,你不学习,不进步,那你就只能被退休。连Java都开始改变他的语法了,你都不准备改变吗 + + + +这篇文章,我不准备直接讲语法,因为基本每个人第一次看到 lambda语法直接就懵的。讲了也记不住,不理解,不会用,到时候讲了也是白讲 + +我用个小例子讲述下,我们在做crud的时候,都是怎么完成功能的。然后怎么根据需求变更版本,最后再讲lambda表达式 + +如果想运用lambda表达式,使用JDK8的另一个新特性 Stream ,效果会更好,可以参考我的这篇文章 [JDK8 新特性stream](https://github.com/leosanqing/Java-Notes/tree/master/Utils/jdk8%E6%96%B0%E7%89%B9%E6%80%A7/stream) + +# 背景 + + + +假设我们现在在做一个 **学生管理系统**(类似于这种的管理系统,我想基本应该都做过)。 + +我们在写**service**部分,根据需求来编写相应的方法 + + + +## 项目结构 + + + +> Ps: 没有用严格的项目结构,但是大致懂就行啦 + +![](img/Xnip2020-01-21_12-18-36.jpg) + +## 基本类 + +```java +package com.leosanqing; + +import lombok.AllArgsConstructor; +import lombok.Data; + +/** + * @Author: leosanqing + * @Date: 2020/1/17 上午7:54 + * @Package: com.leosanqing + * @Description: 学生类 + */ +@Data +@AllArgsConstructor +public class Student { + private String name; + private int age; + private String sex; + /** + * 课程 + */ + private String subject; + private int height; + private int weight; + private String teacher; + +} + +``` + + + + + +## list列表 + +学生信息分别都是这些 + +```java +private static List studentList = new ArrayList() { + { + add(new Student("张三丰", 20, "男", "体育", + 180, 75, "太上老君")); + add(new Student("张无忌", 18, "男", "语文", + 178, 73, "文曲星")); + add(new Student("赵敏", 17, "女", "数学", + 170, 50, "太白金星")); + add(new Student("金毛狮王", 25, "男", "体育", + 176, 80, "太白金星")); + add(new Student("周芷若", 16, "女", "语文", + 168, 48, "太上老君")); + add(new Student("张三", 21, "男", "英语", + 172, 65, "如来")); + add(new Student("赵勇", 26, "男", "体育", + 188, 80, "太上老君")); + + + } + }; +``` + + + +## 版本一 + +**我找出所有学生中的女学生** + +这个应该很简单,只需要将写个过滤条件就行 + +```java + /** + * 版本一 + * 找出女学生 + * + * @return + */ + public static List getFemaleStudent(List studentList) { + List students = new ArrayList<>(); + for (Student student : studentList) { + if ("女".equals(student.getSex())) { + students.add(student); + } + } + return students; + } +``` + + + +## 版本二 + +上面的太死了,只能找出女学生。**我要能根据输入的性别来找**。将性别作为参数传进入 + +```java + /** + * 版本二 + *

+ * 根据输入性别查找学生 + * + * @param studentList + * @param sex + * @return + */ + public static List getStudentBySex(List studentList, String sex) { + List students = new ArrayList<>(); + for (Student student : studentList) { + if (sex.equals(student.getSex())) { + students.add(student); + } + } + return students; + } + +``` + +## 版本三 + +你这个功能太少了,我要不仅能 **根据输入的年龄或者老师查找**,**也能根据年龄查找的功能**的方法。那我们就多设置几个参数,把那些要求都作为参数传进入 + +```java + + /** + * 版本三 + *

+ * 根据输入的年龄或者老师查找。true表示使用年龄,false表示使用老师这个参数 + * + * @param studentList + * @param age + * @return + */ + public static List getStudentByAgeOrTeacher(List studentList, int age, + String teacher, boolean ageOrTeacher) { + List students = new ArrayList<>(); + for (Student student : studentList) { + if ((ageOrTeacher && student.getAge() > age) + || !ageOrTeacher && teacher.equals(student.getTeacher()) + ) { + + students.add(student); + } + } + return students; + } +``` + +## 版本四 + +版本三解决了一个需求,但是如果我的需求复杂,要求多呢?我就要输入n多个参数 + +这个时候,我们就要将其抽象一下,使用面向对象的思想。用一下 策略者模式。(严格意义上说,虽然用Java编程,但是很多人根本连Java都没有入门,因为没有用过 面向对象的思想,基本全是面向过程 。你自己定义过 接口,使用过多态吗?使用过抽象类吗?使用过继承吗?Spring框架很强大,强大到很多人都变"笨"了,我只需要crud,其他的大部分框架已经帮忙做了,我也不需要怎么设计,不用考虑怎么抽出通用的类和方法) + + + +我们定义一个接口 + +```java +package com.leosanqing.predicate; + +import com.leosanqing.bean.Student; + +/** + * @Author: leosanqing + * @Date: 2020/1/19 下午11:41 + * @Package: com.leosanqing.service + * @Description: 学生条件接口 + */ +public interface StudentPredicate { + boolean filter(Student student); +} + +``` + +来两个实现类 + +```java +package com.leosanqing.predicate; + +import com.leosanqing.bean.Student; + +/** + * @Author: leosanqing + * @Date: 2020/1/19 下午11:49 + * @Package: com.leosanqing.predicate + * @Description: 根据年龄过滤 + */ +public class AgePredicate implements StudentPredicate { + @Override + public boolean filter(Student student) { + return student.getAge() > 20; + } +} + +``` + + + +```java +package com.leosanqing.predicate; + +import com.leosanqing.bean.Student; + +/** + * @Author: leosanqing + * @Date: 2020/1/19 下午11:51 + * @Package: com.leosanqing.predicate + * @Description: 根据老师过滤 + */ +public class TeacherPredicate implements StudentPredicate{ + @Override + public boolean filter(Student student) { + return "如来".equals(student.getTeacher()); + } +} + +``` + + + +```java + /** + * 版本四 + * + * 使用多态完成,使用策略者模式 + * @param studentList + * @param predicate + * @return + */ + public static List filterStudent(List studentList, StudentPredicate predicate) { + List students = new ArrayList<>(); + for (Student student : studentList) { + if(predicate.filter(student)){ + students.add(student); + } + } + return students; + } +``` + + + +## 版本五 + +我们觉得这个这个太麻烦了,我们只想用的时候再对其进行实现。因此便有了匿名内部类 + + + +```java + /** + * 版本五,使用匿名内部类。 使用Test测试的时候就是在使用这个方法,我们在使用的时候才去实现具体的方法 + */ + @Test + public void anonymousInnerClass(){ + final List studentList = StudentService.getStudentList(); + final List students = StudentService.filterStudent(studentList, new StudentPredicate() { + @Override + public boolean filter(Student student) { + return "如来".equals(student.getTeacher()); + } + }); + System.out.println(JSON.toJSONString(students,true)); + + } + +``` + +## 版本六 + +匿名内部类已经够简单的了吧?但是我们还想再简单点,这个时候 lambda就出来了 + +```java + /** + * 版本六,使用lambda + */ + @Test + public void lambda(){ + final List studentList = StudentService.getStudentList(); + final List students = StudentService.filterStudent(studentList, student -> "如来".equals(student.getTeacher())); + System.out.println(JSON.toJSONString(students,true)); + + } +``` + +我们看,**lambda表达式其实和匿名内部类结构有点类似**。 + + + +通过这样的介绍,现在你应该知道 lambda 表达式 其实也没有那么难理解了吧,你就把他当成**匿名函数**来理解会容易的多 + +在我上大学的时候,那个时候还在讲Java的GUI,当我们定义按钮和何种监听器的时候,为了方便,几乎都用匿名内部类来完成。 + +再比如我们使用 多线程的时候 + +```java +new Thread(new Runnable() { + @Override + public void run() { + + } + }); +``` + +那我们就可以用lambda写成这样子的 + +```java +new Thread(()->{ + //这个里面写的就是run方法里面的内容 +}); +``` + + + + + +# 接口 + +| 函数式接口 | 参数类型 | 返回类型 | 用途 | +| ------------------------- | -------- | ----------- | ----------------------------------------------------------- | +| **Consumer(消费型接口)** | **T** | **void** | **对类型为T的对象应用操作。void accept(T t)** | +| **Supplier(供给型接口)** | **无** | **T** | **返回类型为T的对象。 T get();** | +| **Function(函数型接口)** | **T** | **R** | **对类型为T的对象应用操作并返回R类型的对象。R apply(T t);** | +| **Predicate(断言型接口)** | **T** | **boolean** | **确定类型为T的对象是否满足约束。boolean test(T t);** | + + 上面是我们常用到的四种函数接口,我们之前代码展示的就是 Predicate的接口,我们使用的 filter方法,返回的是一个 bool值 + +如果想了解或者实战,使用stream编程的时候会更深刻,可以看看我的这篇文章。 [Stream流编程](https://github.com/leosanqing/Java-Notes/tree/master/Utils/jdk8%E6%96%B0%E7%89%B9%E6%80%A7/stream) + + + +那么如果我们自己定义一个你能够使用 lambda表达式的接口,应该注意什么呢 + +## 条件 + +**接口中有且只有一个抽象方法** + + + +我们看到我们的代码中,我们的接口中只有 filter 这一个抽象方法。 + +我们自己定义的时候,可以使用jdk8 新提供的一个注解 `@FunctionalInterface` ,这个没有其他作用,就是标示他是一个函数式接口,也就是能够直接用来写lambda表达式的接口。不满足条件的就会报错 + +比如我们接口中没有抽象方法,或者抽象方法有两个及以上就会报以下的错误 + +![](img/Xnip2020-02-11_12-42-10.jpg) + +![Xnip2020-02-11_12-42-34](img/Xnip2020-02-11_12-42-34.jpg) + +# 方法引用 + +我们有时候会看到这样的代码 + + + +```java + public void peekTest() { + studentList.stream() + .peek(System.out::println) + .sorted(Comparator.comparingInt(Student::getAge)) + .forEach(stu -> System.out.println(JSON.toJSONString(stu, true))); + } +``` + + + +第一次看这个的时候肯定会懵,这个双冒号是什么鬼? + +其实这个是 **方法引用** + +## 定义 + +方法引用 是 **lambda表达式的一种快捷写法**,记住他是lambda的一种快捷写法,要**先能写成lambda才能写成 方法引用** + +```javascript +Stu :: getAge +目标引用 双冒号 方法名 +``` + +## 类型 + +1. 指向 静态方法的方法引用 + + ```java + public void test1(){ + Consumer consumer1 = number -> Integer.parseInt(number); + + Consumer consumer2 = Integer::parseInt; + + } + ``` + + + +2. 指向现有对象的实例方法的方法引用 + + ```java + public void test2(){ + Consumer consumer1 = number -> number.length(); + + Consumer consumer2 = String::length; + + } + ``` + + + +3. 指向任意类型实例方法的方法引用 + + ```java + public void test3(){ + + StringBuilder stringBuilder = new StringBuilder(); + Consumer consumer1 = number -> stringBuilder.append(number); + + Consumer consumer2 = stringBuilder::append; + + } + + ``` + + \ No newline at end of file diff --git "a/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/img/Xnip2020-01-21_12-18-36.jpg" "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/img/Xnip2020-01-21_12-18-36.jpg" new file mode 100644 index 0000000..27de410 Binary files /dev/null and "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/img/Xnip2020-01-21_12-18-36.jpg" differ diff --git "a/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/img/Xnip2020-02-11_12-42-10.jpg" "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/img/Xnip2020-02-11_12-42-10.jpg" new file mode 100644 index 0000000..26d1437 Binary files /dev/null and "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/img/Xnip2020-02-11_12-42-10.jpg" differ diff --git "a/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/img/Xnip2020-02-11_12-42-34.jpg" "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/img/Xnip2020-02-11_12-42-34.jpg" new file mode 100644 index 0000000..26f6430 Binary files /dev/null and "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/img/Xnip2020-02-11_12-42-34.jpg" differ diff --git "a/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/.idea/compiler.xml" "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/.idea/compiler.xml" new file mode 100644 index 0000000..eaf6f39 --- /dev/null +++ "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/.idea/compiler.xml" @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git "a/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/.idea/encodings.xml" "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/.idea/encodings.xml" new file mode 100644 index 0000000..63e9001 --- /dev/null +++ "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/.idea/encodings.xml" @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git "a/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/.idea/misc.xml" "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/.idea/misc.xml" new file mode 100644 index 0000000..3ccb27b --- /dev/null +++ "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/.idea/misc.xml" @@ -0,0 +1,17 @@ + + + + + + + + + + + + \ No newline at end of file diff --git "a/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/.idea/uiDesigner.xml" "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/.idea/uiDesigner.xml" new file mode 100644 index 0000000..e96534f --- /dev/null +++ "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/.idea/uiDesigner.xml" @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git "a/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/pom.xml" "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/pom.xml" new file mode 100644 index 0000000..0a0c1f7 --- /dev/null +++ "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/pom.xml" @@ -0,0 +1,42 @@ + + + 4.0.0 + + org.example + lambda_demo + 1.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + 2.1.5.RELEASE + + + + + + org.projectlombok + lombok + 1.18.10 + provided + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + + + + com.alibaba + fastjson + 1.2.4 + + + + + \ No newline at end of file diff --git "a/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/src/main/java/com/leosanqing/Student.java" "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/src/main/java/com/leosanqing/Student.java" new file mode 100644 index 0000000..c62b23f --- /dev/null +++ "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/src/main/java/com/leosanqing/Student.java" @@ -0,0 +1,26 @@ +package com.leosanqing; + +import lombok.AllArgsConstructor; +import lombok.Data; + +/** + * @Author: leosanqing + * @Date: 2020/1/17 上午7:54 + * @Package: com.leosanqing + * @Description: 学生类 + */ +@Data +@AllArgsConstructor +public class Student { + private String name; + private int age; + private String sex; + /** + * 课程 + */ + private String subject; + private int height; + private int weight; + private String teacher; + +} diff --git "a/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/src/main/java/com/leosanqing/cart/Sku.java" "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/src/main/java/com/leosanqing/cart/Sku.java" new file mode 100644 index 0000000..6add2dc --- /dev/null +++ "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/src/main/java/com/leosanqing/cart/Sku.java" @@ -0,0 +1,20 @@ +package com.leosanqing.cart; + +import com.leosanqing.enums.CategoryEnum; +import lombok.Data; + +/** + * @Author: leosanqing + * @Date: 2020/1/16 上午8:23 + * @Package: com.leosanqing.cart + * @Description: 购物车商品规格对象 + */ +@Data +public class Sku { + private Integer skuId; + private String name; + private Double price; + private Integer totalNum; + private Double totalPrice; + private Enum category; +} diff --git "a/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/src/main/java/com/leosanqing/enums/CategoryEnum.java" "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/src/main/java/com/leosanqing/enums/CategoryEnum.java" new file mode 100644 index 0000000..0527718 --- /dev/null +++ "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/src/main/java/com/leosanqing/enums/CategoryEnum.java" @@ -0,0 +1,26 @@ +package com.leosanqing.enums; + +import lombok.Getter; + +/** + * @Author: leosanqing + * @Date: 2020/1/16 上午8:26 + * @Package: com.leosanqing.cart + * @Description: 分类枚举 + */ +public enum CategoryEnum { + FOOD(10,"食品"), + CLOTHING(20,"衣服"), + BOOK(30,"图书"), + ELECTRONIC(40,"电子"), + + + ; + private int code; + private String name; + + CategoryEnum(int code,String name){ + this.code = code; + this.name = name; + } +} diff --git "a/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/src/main/java/com/leosanqing/predicate/AgePredicate.java" "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/src/main/java/com/leosanqing/predicate/AgePredicate.java" new file mode 100644 index 0000000..9a5509f --- /dev/null +++ "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/src/main/java/com/leosanqing/predicate/AgePredicate.java" @@ -0,0 +1,16 @@ +package com.leosanqing.predicate; + +import com.leosanqing.Student; + +/** + * @Author: leosanqing + * @Date: 2020/1/19 下午11:49 + * @Package: com.leosanqing.predicate + * @Description: 根据年龄过滤 + */ +public class AgePredicate implements StudentPredicate { + @Override + public boolean filter(Student student) { + return student.getAge() > 20; + } +} diff --git "a/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/src/main/java/com/leosanqing/predicate/StudentPredicate.java" "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/src/main/java/com/leosanqing/predicate/StudentPredicate.java" new file mode 100644 index 0000000..436a26a --- /dev/null +++ "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/src/main/java/com/leosanqing/predicate/StudentPredicate.java" @@ -0,0 +1,13 @@ +package com.leosanqing.predicate; + +import com.leosanqing.Student; + +/** + * @Author: leosanqing + * @Date: 2020/1/19 下午11:41 + * @Package: com.leosanqing.service + * @Description: 学生条件接口 + */ +public interface StudentPredicate { + boolean filter(Student student); +} diff --git "a/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/src/main/java/com/leosanqing/predicate/TeacherPredicate.java" "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/src/main/java/com/leosanqing/predicate/TeacherPredicate.java" new file mode 100644 index 0000000..b80f5d2 --- /dev/null +++ "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/src/main/java/com/leosanqing/predicate/TeacherPredicate.java" @@ -0,0 +1,16 @@ +package com.leosanqing.predicate; + +import com.leosanqing.Student; + +/** + * @Author: leosanqing + * @Date: 2020/1/19 下午11:51 + * @Package: com.leosanqing.predicate + * @Description: 根据老师过滤 + */ +public class TeacherPredicate implements StudentPredicate{ + @Override + public boolean filter(Student student) { + return "如来".equals(student.getTeacher()); + } +} diff --git "a/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/src/main/java/com/leosanqing/service/StudentService.java" "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/src/main/java/com/leosanqing/service/StudentService.java" new file mode 100644 index 0000000..4b8aabe --- /dev/null +++ "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/src/main/java/com/leosanqing/service/StudentService.java" @@ -0,0 +1,121 @@ +package com.leosanqing.service; + +import com.leosanqing.Student; +import com.leosanqing.predicate.StudentPredicate; + +import java.util.ArrayList; +import java.util.List; + +/** + * @Author: leosanqing + * @Date: 2020/1/17 上午7:58 + * @Package: com.leosanqing.service + * @Description: 学生服务类 + */ +public class StudentService { + private static List studentList = new ArrayList() { + { + add(new Student("张三丰", 20, "男", "体育", + 180, 75, "太上老君")); + add(new Student("张无忌", 18, "男", "语文", + 178, 73, "文曲星")); + add(new Student("赵敏", 17, "女", "数学", + 170, 50, "太白金星")); + add(new Student("金毛狮王", 25, "男", "体育", + 176, 80, "太白金星")); + add(new Student("周芷若", 16, "女", "语文", + 168, 48, "太上老君")); + add(new Student("张三", 21, "男", "英语", + 172, 65, "如来")); + add(new Student("赵勇", 26, "男", "体育", + 188, 80, "太上老君")); + + + } + }; + + + public static List getStudentList() { + return studentList; + } + + /** + * 版本一 + * 找出女学生 + * + * @return + */ + public static List getFemaleStudent(List studentList) { + List students = new ArrayList<>(); + for (Student student : studentList) { + if ("女".equals(student.getSex())) { + students.add(student); + } + } + return students; + } + + /** + * 版本二 + *

+ * 根据输入性别查找学生 + * + * @param studentList + * @param sex + * @return + */ + public static List getStudentBySex(List studentList, String sex) { + List students = new ArrayList<>(); + for (Student student : studentList) { + if (sex.equals(student.getSex())) { + students.add(student); + } + } + return students; + } + + /** + * 版本三 + *

+ * 根据输入的年龄或者老师查找。true表示使用年龄,false表示使用老师这个参数 + * + * @param studentList + * @param age + * @return + */ + public static List getStudentByAgeOrTeacher(List studentList, int age, + String teacher, boolean ageOrTeacher) { + List students = new ArrayList<>(); + for (Student student : studentList) { + if ((ageOrTeacher && student.getAge() > age) + || !ageOrTeacher && teacher.equals(student.getTeacher()) + ) { + + students.add(student); + } + } + return students; + } + + + /** + * 版本四 + * + * 使用多态完成,使用策略者模式 + * @param studentList + * @param predicate + * @return + */ + public static List filterStudent(List studentList, StudentPredicate predicate) { + List students = new ArrayList<>(); + for (Student student : studentList) { + if(predicate.filter(student)){ + students.add(student); + } + } + return students; + } + + + +} diff --git "a/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/src/test/java/lambda/VersionTest.java" "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/src/test/java/lambda/VersionTest.java" new file mode 100644 index 0000000..ef7a36b --- /dev/null +++ "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/src/test/java/lambda/VersionTest.java" @@ -0,0 +1,108 @@ +package lambda; + +import com.alibaba.fastjson.JSON; +import com.leosanqing.Student; +import com.leosanqing.predicate.AgePredicate; +import com.leosanqing.predicate.StudentPredicate; +import com.leosanqing.predicate.TeacherPredicate; +import com.leosanqing.service.StudentService; +import org.junit.Test; + +import java.util.List; + +/** + * @Author: leosanqing + * @Date: 2020/1/17 上午8:20 + * @Package: lambda + * @Description: 版本测试 + */ + +public class VersionTest { + + + /** + * 第一版 + * + * 根据性别查找 + */ + @Test + public void getFemaleStudent(){ + final List studentList = StudentService.getStudentList(); + + final List femaleStudents = StudentService.getFemaleStudent(studentList); + + System.out.println(JSON.toJSONString(femaleStudents,true)); + + } + + + /** + * 第二版 根据输入性别查找 + */ + @Test + public void getStudentBySex(){ + final List studentList = StudentService.getStudentList(); + + final List femaleStudents = StudentService.getStudentBySex(studentList,"男"); + + System.out.println(JSON.toJSONString(femaleStudents,true)); + + } + + /** + * 版本三: 根据两个参数判断查找 + */ + @Test + public void getStudentByAgeOrTeacher(){ + final List studentList = StudentService.getStudentList(); + + final List studentByAgeOrTeacher = StudentService.getStudentByAgeOrTeacher(studentList, 20, null, true); + System.out.println(JSON.toJSONString(studentByAgeOrTeacher,true)); + + + } + + /** + * 版本四,使用接口,策略者模式 + */ + @Test + public void filterStudent(){ + final List studentList = StudentService.getStudentList(); + + final TeacherPredicate teacherPredicate = new TeacherPredicate(); + + final List students = StudentService.filterStudent(studentList,teacherPredicate); + System.out.println(JSON.toJSONString(students,true)); + + } + + + /** + * 版本五,使用匿名内部类 + */ + @Test + public void AnonymousInnerClass(){ + final List studentList = StudentService.getStudentList(); + final List students = StudentService.filterStudent(studentList, new StudentPredicate() { + @Override + public boolean filter(Student student) { + return "如来".equals(student.getTeacher()); + } + }); + System.out.println(JSON.toJSONString(students,true)); + + } + + + /** + * 版本五,使用lambda + */ + @Test + public void lambda(){ + final List studentList = StudentService.getStudentList(); + final List students = StudentService.filterStudent(studentList, student -> "如来".equals(student.getTeacher())); + System.out.println(JSON.toJSONString(students,true)); + + } + +} diff --git "a/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/target/.DS_Store" "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/target/.DS_Store" new file mode 100644 index 0000000..5008ddf Binary files /dev/null and "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/lambda/lambda_demo/target/.DS_Store" differ diff --git "a/Utils/jdk8\346\226\260\347\211\271\346\200\247/stream/README.md" "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/stream/README.md" new file mode 100644 index 0000000..57bb386 --- /dev/null +++ "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/stream/README.md" @@ -0,0 +1,1060 @@ +# 前言 + +我们前面说了 lambda表达式,这次我们就将下JDK8的另一个新特性,**流(Stream)** + +stream和lambda‘搭配使用效果更佳,(如果你没有学过lambda表达式,最好先学习下[lambda表达式](https://github.com/leosanqing/Java-Notes/tree/master/Utils/jdk8%E6%96%B0%E7%89%B9%E6%80%A7/lambda)) + + + +看着逼格也更高,也更简洁 + +我们就拿之前的lambda表达式的举例 + +我们需要找出集合中所有的 男同学 按照年龄从小到大排序 并且打印出来,我们就这样写 + +```java +studentList.stream() + .filter(student -> "男".equals(student.getSex())) + .sorted((x, y) -> x.getAge()-y.getAge()) + .forEach(student -> System.out.println(JSON.toJSONString(student, true))); +``` + + + +代码在本目录下的 lambda_demo ,演示在这个测试文件下 + +![](img/Xnip2020-02-11_13-40-12.jpg) + + + +# 定义 + +Stream(流)是一个来自**数据源**的**元素队列**并支持**聚合操作** + +- 元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。 +- **数据源** 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。 +- **聚合操作** 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。 + + + +流的处理流程一般是这样 + +``` ++--------------------+ +------+ +------+ +---+ +-------+ +| stream of elements +-----> |filter+-> |sorted+-> |map+-> |collect| ++--------------------+ +------+ +------+ +---+ +-------+ +``` + + + +聚合操作按照分法可以分成两种:**中间操作,终端操作** + +- 中间操作 + - 无状态操作 + - filter、map、peek等 + - 有状态操作 + - Sorted、distinct、limit等 +- 终端操作 + - 非短路操作 + - foreach、count、collect等 + - 短路操作 + - findFirst、findAny、anyMatch等 + +**中间操作** + +中间操作和很多命令像不像我们 sql 里面的命令,你可以理解为我们的那些限制语句,通过这些手段得到我们想要的一些数据 + +**终端操作** + +顾名思义,就是指最后的操作。一个流里面进行完终端操作之后就不能再进行其他操作了 + +**无状态操作** + +就是不需要全部遍历完之后才能得到,比如 我上面的代码,我只看这个元素符不符合,不符合我就不要,不需要遍历完全部元素。与此相对,有状态操作就是需要整个集合遍历完才行,比如我们的 sorted,我不遍历完所有元素,我怎么知道哪一个最大,哪一个最小 + +**短路操作** + +就是找到一个我们就不往下执行了。与此相反,非短路操作也很好理解 + +# 各个方法演示 + +我的集合中有如下元素 + +```java +private static List studentList = new ArrayList() { + { + add(new Student("张三丰", 20, "男", "体育", + 180, 75, "太上老君")); + add(new Student("张无忌", 18, "男", "语文", + 178, 73, "文曲星")); + add(new Student("赵敏", 17, "女", "数学", + 170, 50, "太白金星")); + add(new Student("金毛狮王", 25, "男", "体育", + 176, 80, "太白金星")); + add(new Student("周芷若", 16, "女", "语文", + 168, 48, "太上老君")); + add(new Student("张三", 21, "男", "英语", + 172, 65, "如来")); + add(new Student("赵勇", 26, "男", "体育", + 188, 80, "太上老君")); + + + } + }; + +``` + + + + + +## 中间操作 + +### 无状态操作 + +#### filter + +filter,就是过滤掉那些不符合你设定的条件的元素 + +我们看源码 + +```java +/** + * Returns a stream consisting of the elements of this stream that match + * the given predicate. + * + *

This is an intermediate + * operation. + * + * @param predicate a non-interfering, + * stateless + * predicate to apply to each element to determine if it + * should be included + * @return the new stream + */ + Stream filter(Predicate predicate); + +// 再看他的参数,记不记得我当初 讲 lambda 时候讲到的 这个 +// Predicate 接口 是输入一个类型,返回一个bool值 + +@FunctionalInterface +public interface Predicate { + + /** + * Evaluates this predicate on the given argument. + * + * @param t the input argument + * @return {@code true} if the input argument matches the predicate, + * otherwise {@code false} + */ + boolean test(T t); +} +``` + +所以我们使用的时候,返回的是一个bool值,如下所示 + +Equals 方法返回的是一个bool值 + +```java +studentList.stream() + .filter(student -> "男".equals(student.getSex())) + .forEach(student -> System.out.println(JSON.toJSONString(student, true))); + +``` + +结果,我们看到它里面已经过滤掉了女同学 + +```javascript +{ + "age":20, + "height":180, + "name":"张三丰", + "sex":"男", + "subject":"体育", + "teacher":"太上老君", + "weight":75 +} +{ + "age":18, + "height":178, + "name":"张无忌", + "sex":"男", + "subject":"语文", + "teacher":"文曲星", + "weight":73 +} +{ + "age":25, + "height":176, + "name":"金毛狮王", + "sex":"男", + "subject":"体育", + "teacher":"太白金星", + "weight":80 +} +{ + "age":21, + "height":172, + "name":"张三", + "sex":"男", + "subject":"英语", + "teacher":"如来", + "weight":65 +} +{ + "age":26, + "height":188, + "name":"赵勇", + "sex":"男", + "subject":"体育", + "teacher":"太上老君", + "weight":80 +} + + +``` + + + +#### map + +map的作用是,将一个类型的集合转化为另一个类型的集合 + +我们来看他的源码 + +```java + /** + * Returns a stream consisting of the results of applying the given + * function to the elements of this stream. + * + *

This is an intermediate + * operation. + * @return the new stream + */ + Stream map(Function mapper); + + + // 他要传入的是一个 Function 接口,作用是输入一个类型,返回另一个类型 + @FunctionalInterface + public interface Function { + + /** + * Applies this function to the given argument. + * + * @param t the function argument + * @return the function result + */ + R apply(T t); + } +``` + +我们用它生成一个 学生选课的集合。我们输入的是一个Student类型的集合,返回的是一个 String类型的集合 + +```java + @Test + public void mapTest(){ + + studentList.stream() + .map(student -> student.getSubject()) + .forEach(student -> System.out.println(JSON.toJSONString(student, true))); + } +``` + +结果如下 + +``` +"体育" +"语文" +"数学" +"体育" +"语文" +"英语" +"体育" +``` + +#### faltMap + +将一个类型的集合转换成另一个类型的流(注意和map区分) + +```java +/** + * Returns a stream consisting of the results of replacing each element of + * this stream with the contents of a mapped stream produced by applying + * the provided mapping function to each element. Each mapped stream is + * {@link java.util.stream.BaseStream#close() closed} after its contents + * have been placed into this stream. (If a mapped stream is {@code null} + * an empty stream is used, instead.) + * + * @return the new stream + */ + Stream flatMap(Function> mapper); + + + // 他也是 Function接口,但是另一个参数是继承自 Stream类的 +``` + +```java + /** + * 将一个类型的集合抓换成流.我们把一个字符串流转换成一个字符流 + */ + @Test + public void flatMapTest() { + + studentList.stream() + .flatMap(student -> Arrays.stream(student.getName().split(""))) + .forEach(stu -> System.out.println(JSON.toJSONString(stu,true))); + } +``` + +#### peek + +peek和foreach很相似,区别是 ,一个是中间操作,一个是终端操作。peek用完之后还能被其他操作进行处理。 + +```java +/** + * Returns a stream consisting of the elements of this stream, additionally + * performing the provided action on each element as elements are consumed + * from the resulting stream. + * + + * @return the new stream + */ + Stream peek(Consumer action); + + +// 我们看到他的函数接口是Consumer,他是输入一个参数,但是不会有返回值 +@FunctionalInterface +public interface Consumer { + + /** + * Performs this operation on the given argument. + * + * @param t the input argument + */ + void accept(T t); +} +``` + +```java + /** + * peek 方法 + */ + @Test + public void peekTest() { + studentList.stream() + .peek(student -> System.out.println(student.getName())) + .forEach(stu -> System.out.println(JSON.toJSONString(stu,true))); + } +``` + +```java +张三丰 +{ + "age":20, + "height":180, + "name":"张三丰", + "sex":"男", + "subject":"体育", + "teacher":"太上老君", + "weight":75 +} +张无忌 +{ + "age":18, + "height":178, + "name":"张无忌", + "sex":"男", + "subject":"语文", + "teacher":"文曲星", + "weight":73 +} +赵敏 +{ + "age":17, + "height":170, + "name":"赵敏", + "sex":"女", + "subject":"数学", + "teacher":"太白金星", + "weight":50 +} +金毛狮王 +{ + "age":25, + "height":176, + "name":"金毛狮王", + "sex":"男", + "subject":"体育", + "teacher":"太白金星", + "weight":80 +} +周芷若 +{ + "age":16, + "height":168, + "name":"周芷若", + "sex":"女", + "subject":"语文", + "teacher":"太上老君", + "weight":48 +} +张三 +{ + "age":21, + "height":172, + "name":"张三", + "sex":"男", + "subject":"英语", + "teacher":"如来", + "weight":65 +} +赵勇 +{ + "age":26, + "height":188, + "name":"赵勇", + "sex":"男", + "subject":"体育", + "teacher":"太上老君", + "weight":80 +} +``` + +我们看到 人名和student类是交替打印的**,也就是执行了一次 peek,执行了一次 foreach**,那么每次都是这样吗?不是的,我们来看下一节 + +### 有状态操作 + +#### sorted + +sorted是用来排序的 + + + +```java + /** + * Returns a stream consisting of the elements of this stream, sorted + * according to the provided {@code Comparator} + * @return the new stream + */ + Stream sorted(Comparator comparator); + + // 他提供了一个 Comparator接口 + @FunctionalInterface + public interface Comparator { + /** + * Compares its two arguments for order. Returns a negative integer, + * zero, or a positive integer as the first argument is less than, equal + * to, or greater than the second.

+ */ + int compare(T o1, T o2); +``` + + + +```java +/** + * sorted 方法,按照年龄大小排序 + */ + @Test + public void sortedTest() { + studentList.stream() + .peek(student -> System.out.println(student.getName())) + .sorted((x,y) -> x.getAge()-y.getAge()) + .forEach(stu -> System.out.println(JSON.toJSONString(stu,true))); + } +``` + +``` +张三丰 +张无忌 +赵敏 +金毛狮王 +周芷若 +张三 +赵勇 +{ + "age":16, + "height":168, + "name":"周芷若", + "sex":"女", + "subject":"语文", + "teacher":"太上老君", + "weight":48 +} +{ + "age":17, + "height":170, + "name":"赵敏", + "sex":"女", + "subject":"数学", + "teacher":"太白金星", + "weight":50 +} +{ + "age":18, + "height":178, + "name":"张无忌", + "sex":"男", + "subject":"语文", + "teacher":"文曲星", + "weight":73 +} +{ + "age":20, + "height":180, + "name":"张三丰", + "sex":"男", + "subject":"体育", + "teacher":"太上老君", + "weight":75 +} +{ + "age":21, + "height":172, + "name":"张三", + "sex":"男", + "subject":"英语", + "teacher":"如来", + "weight":65 +} +{ + "age":25, + "height":176, + "name":"金毛狮王", + "sex":"男", + "subject":"体育", + "teacher":"太白金星", + "weight":80 +} +{ + "age":26, + "height":188, + "name":"赵勇", + "sex":"男", + "subject":"体育", + "teacher":"太上老君", + "weight":80 +} + +``` + + + +我们看到,这次是先打印peek的内容,再打印 foreach的内容,为什么会这样呢? + +**因为之前我们除只有无状态的方法,他不需要遍历完其他全部的操作,所以他就交替打印了,也符合流的特性。但是我们这一次有了有状态的操作,就只能等到处理完全部元素之后能进行foreach的遍历操作** + +#### distinct + +去重 + +```java +/** + * Returns a stream consisting of the distinct elements (according to + * {@link Object#equals(Object)}) of this stream + * + * @return the new stream + */ + Stream distinct(); +``` + + + +```java +/** + * distinct 方法,找出所有老师 + */ +@Test +public void distinctTest() { + studentList.stream() + .map(student -> student.getTeacher()) + .distinct() + .forEach(stu -> System.out.println(JSON.toJSONString(stu,true))); +} +``` + +``` +"太上老君" +"文曲星" +"太白金星" +"如来" +``` + +#### limit + +```java + /** + * Returns a stream consisting of the elements of this stream, truncated + * to be no longer than {@code maxSize} in length. + * + * @param maxSize the number of elements the stream should be limited to + * @return the new stream + * @throws IllegalArgumentException if {@code maxSize} is negative + */ + Stream limit(long maxSize); + + + /** + * limit 方法,只显示前4个 + */ + @Test + public void limitTest() { + studentList.stream() + .limit(4) + .forEach(stu -> System.out.println(JSON.toJSONString(stu,true))); + } +``` + + + +``` +{ + "age":20, + "height":180, + "name":"张三丰", + "sex":"男", + "subject":"体育", + "teacher":"太上老君", + "weight":75 +} +{ + "age":18, + "height":178, + "name":"张无忌", + "sex":"男", + "subject":"语文", + "teacher":"文曲星", + "weight":73 +} +{ + "age":17, + "height":170, + "name":"赵敏", + "sex":"女", + "subject":"数学", + "teacher":"太白金星", + "weight":50 +} +{ + "age":25, + "height":176, + "name":"金毛狮王", + "sex":"男", + "subject":"体育", + "teacher":"太白金星", + "weight":80 +} + +``` + +#### skip + +```java +/** + * Returns a stream consisting of the remaining elements of this stream + * after discarding the first {@code n} elements of the stream. + * If this stream contains fewer than {@code n} elements then an + * empty stream will be returned. + + * @throws IllegalArgumentException if {@code n} is negative + */ + Stream skip(long n); + + + +/** + * skip 方法,跳过前4个 + */ + @Test + public void skipTest() { + studentList.stream() + .skip(4) + .forEach(stu -> System.out.println(JSON.toJSONString(stu,true))); + } +``` + +```java +{ + "age":16, + "height":168, + "name":"周芷若", + "sex":"女", + "subject":"语文", + "teacher":"太上老君", + "weight":48 +} +{ + "age":21, + "height":172, + "name":"张三", + "sex":"男", + "subject":"英语", + "teacher":"如来", + "weight":65 +} +{ + "age":26, + "height":188, + "name":"赵勇", + "sex":"男", + "subject":"体育", + "teacher":"太上老君", + "weight":80 +} +``` + +**skip+limit可以完成分页功能** + +```java + /** + * limit+skip 方法,完成分页功能 + */ + @Test + public void skipAndLimitTest() { + studentList.stream() + .skip(1 * 4) + .limit(4) + .forEach(stu -> System.out.println(JSON.toJSONString(stu, true))); + } +``` + + + +## 终端操作 + +### 短路 + + + +#### anyMatch + +```java + /** + * Returns whether any elements of this stream match the provided + * predicate. May not evaluate the predicate on all elements if not + * necessary for determining the result. If the stream is empty then + * {@code false} is returned and the predicate is not evaluated. + + * @return {@code true} if any elements of the stream match the provided + * predicate, otherwise {@code false} + */ + boolean anyMatch(Predicate predicate); + + + +/** + * anyMatch方法,判断是否有一个满足条件 + */ + @Test + public void anyMatchTest() { + final boolean b = studentList.stream() + .peek(student -> System.out.println(student)) + .allMatch(student -> student.getAge() > 100); + System.out.println(b); + } +``` + +为啥说是**短路操作**。我们测试一下就知道 + +我们看到,它只打印了一个元素。因为第一个就不满足,他就不会再往下执行了,直接返回false + +```java +Student(name=张三丰, age=20, sex=男, subject=体育, height=180, weight=75, teacher=太上老君) +false +``` + + + +#### allMatch + +```java + /** + * Returns whether all elements of this stream match the provided predicate. + * May not evaluate the predicate on all elements if not necessary for + * determining the result. If the stream is empty then {@code true} is + * returned and the predicate is not evaluated + * @return {@code true} if either all elements of the stream match the + * provided predicate or the stream is empty, otherwise {@code false} + */ + + // 我们看到他的接口是一个 Predicate ,这个我们之前介绍过,返回的是一个bool值 + boolean allMatch(Predicate predicate); + + + + + /** + * allMatch方法,判断是否全部满足输入的条件 + */ + @Test + public void allMatchTest() { + final boolean b = studentList.stream() + .allMatch(student -> student.getAge() < 100); + System.out.println(b); + } + +``` + + + +#### findFirst + +```java +/** + * Returns an {@link Optional} describing the first element of this stream, + * or an empty {@code Optional} if the stream is empty. If the stream has + * no encounter order, then any element may be returned. + + * @return an {@code Optional} describing the first element of this stream, + * or an empty {@code Optional} if the stream is empty + * @throws NullPointerException if the element selected is null + */ + + // 他返回的是一个 Optional对象 + Optional findFirst(); + + +/** + * findFirst方法 + */ + @Test + public void findFirstTest() { + final Optional first = studentList.stream() + .peek(student -> System.out.println(student)) + .findFirst(); + System.out.println(first.get()); + } + +``` + +#### findAny + +```java +/** + * Returns an {@link Optional} describing some element of the stream, or an + * empty {@code Optional} if the stream is empty. + * + *

This is a short-circuiting + * terminal operation. + * + *

The behavior of this operation is explicitly nondeterministic; it is + * free to select any element in the stream. This is to allow for maximal + * performance in parallel operations; the cost is that multiple invocations + * on the same source may not return the same result. (If a stable result + * is desired, use {@link #findFirst()} instead.) + * + * @return an {@code Optional} describing some element of this stream, or an + * empty {@code Optional} if the stream is empty + * @throws NullPointerException if the element selected is null + * @see #findFirst() + */ + + // 注意 他的解释中说了,findAny可以发挥并行操作的性能,但是如果你在并行的时候想要一个稳定的结果,要用 findFirst。 + Optional findAny(); + + + /** + * 因为我们使用的是串行的操作,所以并不影响结果,和findFirst 的结果一样 + */ + @Test + public void findAnyTest() { + final Optional first = studentList.stream() + .peek(student -> System.out.println(student)) + .findAny(); + System.out.println(first.get()); + } +``` + +#### max + +```java +/** + * Returns the maximum element of this stream according to the provided + * {@code Comparator}. This is a special case of a + * reduction. + * + *

This is a terminal + * operation. + * + * @param comparator a non-interfering, + * stateless + * {@code Comparator} to compare elements of this stream + * @return an {@code Optional} describing the maximum element of this stream, + * or an empty {@code Optional} if the stream is empty + * @throws NullPointerException if the maximum element is null + */ + // 返回的是一个 Optional类 + Optional max(Comparator comparator); + + + /** + * max 方法测试,输出最大的年龄。如果从这里点进入就是使用的 intStream接口,和之前的还不一样 + */ + @Test + public void maxTest() { + final OptionalInt max = studentList.stream() + .mapToInt(stu -> stu.getAge()) + .max(); + System.out.println(max.getAsInt()); + } + + +``` + +### 终端非短路 + +### collect + +```java + + + @Test + public void collectTest(){ + final List list = studentList.stream() + .filter(student -> "女".equals(student.getSex())) + .collect(Collectors.toList()); + + System.out.println(JSON.toJSONString(list,true)); + } +``` + +``` +[ + { + "age":17, + "height":170, + "name":"赵敏", + "sex":"女", + "subject":"数学", + "teacher":"太白金星", + "weight":50 + }, + { + "age":16, + "height":168, + "name":"周芷若", + "sex":"女", + "subject":"语文", + "teacher":"太上老君", + "weight":48 + } +] +``` + + + +groupBy 进行分类 + +```JAVA +/** + * Returns a {@code Collector} implementing a "group by" operation on + * input elements of type {@code T}, grouping elements according to a + * classification function, and returning the results in a {@code Map}. + * + *

The classification function maps elements to some key type {@code K}. + * The collector produces a {@code Map>} whose keys are the + * values resulting from applying the classification function to the input + * elements, and whose corresponding values are {@code List}s containing the + * input elements which map to the associated key under the classification + * function. + */ + + // 可以看到,他的参数也是一个 Function接口, + public static Collector>> + groupingBy(Function classifier) { + return groupingBy(classifier, toList()); + } + + + + @Test + public void collectTest(){ +// final List list = studentList.stream() +// .filter(student -> "女".equals(student.getSex())) +// .collect(Collectors.toList()); + + // 按照性别分类 + final Map> list = studentList.stream() + .collect(Collectors.groupingBy(s -> s.getSex())); + + System.out.println(JSON.toJSONString(list,true)); + } + + +``` + +```java +{ + "女":[ + { + "age":17, + "height":170, + "name":"赵敏", + "sex":"女", + "subject":"数学", + "teacher":"太白金星", + "weight":50 + }, + { + "age":16, + "height":168, + "name":"周芷若", + "sex":"女", + "subject":"语文", + "teacher":"太上老君", + "weight":48 + } + ], + "男":[ + { + "age":20, + "height":180, + "name":"张三丰", + "sex":"男", + "subject":"体育", + "teacher":"太上老君", + "weight":75 + }, + { + "age":18, + "height":178, + "name":"张无忌", + "sex":"男", + "subject":"语文", + "teacher":"文曲星", + "weight":73 + }, + { + "age":25, + "height":176, + "name":"金毛狮王", + "sex":"男", + "subject":"体育", + "teacher":"太白金星", + "weight":80 + }, + { + "age":21, + "height":172, + "name":"张三", + "sex":"男", + "subject":"英语", + "teacher":"如来", + "weight":65 + }, + { + "age":26, + "height":188, + "name":"赵勇", + "sex":"男", + "subject":"体育", + "teacher":"太上老君", + "weight":80 + } + ] +} + +Process finished with exit code 0 + +``` + diff --git "a/Utils/jdk8\346\226\260\347\211\271\346\200\247/stream/img/Xnip2020-02-11_13-40-12.jpg" "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/stream/img/Xnip2020-02-11_13-40-12.jpg" new file mode 100644 index 0000000..0854d05 Binary files /dev/null and "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/stream/img/Xnip2020-02-11_13-40-12.jpg" differ diff --git "a/Utils/jdk8\346\226\260\347\211\271\346\200\247/stream/lambda_demo/.idea/$CACHE_FILE$" "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/stream/lambda_demo/.idea/$CACHE_FILE$" new file mode 100644 index 0000000..6cb8985 --- /dev/null +++ "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/stream/lambda_demo/.idea/$CACHE_FILE$" @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git "a/Utils/jdk8\346\226\260\347\211\271\346\200\247/stream/lambda_demo/.idea/compiler.xml" "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/stream/lambda_demo/.idea/compiler.xml" new file mode 100644 index 0000000..eaf6f39 --- /dev/null +++ "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/stream/lambda_demo/.idea/compiler.xml" @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git "a/Utils/jdk8\346\226\260\347\211\271\346\200\247/stream/lambda_demo/.idea/encodings.xml" "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/stream/lambda_demo/.idea/encodings.xml" new file mode 100644 index 0000000..63e9001 --- /dev/null +++ "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/stream/lambda_demo/.idea/encodings.xml" @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git "a/Utils/jdk8\346\226\260\347\211\271\346\200\247/stream/lambda_demo/.idea/misc.xml" "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/stream/lambda_demo/.idea/misc.xml" new file mode 100644 index 0000000..3ccb27b --- /dev/null +++ "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/stream/lambda_demo/.idea/misc.xml" @@ -0,0 +1,17 @@ + + + + + + + + + + + + \ No newline at end of file diff --git "a/Utils/jdk8\346\226\260\347\211\271\346\200\247/stream/lambda_demo/.idea/uiDesigner.xml" "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/stream/lambda_demo/.idea/uiDesigner.xml" new file mode 100644 index 0000000..e96534f --- /dev/null +++ "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/stream/lambda_demo/.idea/uiDesigner.xml" @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git "a/Utils/jdk8\346\226\260\347\211\271\346\200\247/stream/lambda_demo/.idea/workspace.xml" "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/stream/lambda_demo/.idea/workspace.xml" new file mode 100644 index 0000000..268ecb9 --- /dev/null +++ "b/Utils/jdk8\346\226\260\347\211\271\346\200\247/stream/lambda_demo/.idea/workspace.xml" @@ -0,0 +1,219 @@ + + + + + + + + + + true + + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - true @@ -181,68 +54,43 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -