├── .gitignore ├── .obsidian ├── app.json ├── appearance.json ├── community-plugins.json ├── core-plugins-migration.json ├── core-plugins.json ├── hotkeys.json ├── plugins │ └── table-editor-obsidian │ │ ├── data.json │ │ ├── main.js │ │ ├── manifest.json │ │ └── styles.css └── workspace.json ├── README.md ├── pom.xml └── src └── main ├── java └── cc │ └── tianbin │ ├── algorithm_practice │ ├── Coding_Interview_Guide_2ndEdition │ │ ├── Chapter_01_栈和队列 │ │ │ ├── P01_GetMinStack.java │ │ │ ├── P02_由两个栈组成的队列.java │ │ │ ├── P03_使用递归逆序一个栈.java │ │ │ ├── P04_猫狗队列.java │ │ │ ├── P05_用一个栈实现另一个栈的排序.java │ │ │ ├── P06_用栈来解决汉诺塔问题.java │ │ │ ├── P07_生成窗口最大值数组.java │ │ │ ├── P08_单调栈结构.java │ │ │ ├── P09_求最大子矩阵的大小.java │ │ │ ├── P10_最大值减去最小值小于或等于num的子数组数量.java │ │ │ └── P11_可见的山峰对数量.java │ │ ├── Chapter_04_递归和动态规划 │ │ │ ├── P01_斐波那契数列.java │ │ │ ├── P02_矩阵的最小路径和.java │ │ │ └── P03_机器人达到指定位置方法数.java │ │ └── README.md │ ├── LeetCode │ │ ├── code000 │ │ │ ├── E001_两数之和.java │ │ │ ├── E035_搜索插入位置.java │ │ │ ├── E069_x的平方根.java │ │ │ ├── E083_删除排序链表中的重复元素.java │ │ │ ├── H004_寻找两个有序数组的中位数.java │ │ │ ├── H042_接雨水.java │ │ │ ├── H051_N皇后.java │ │ │ ├── H057_插入区间.java │ │ │ ├── H072_编辑距离.java │ │ │ ├── H084_柱状图中最大的矩形.java │ │ │ ├── H085_最大矩形.java │ │ │ ├── M002_两数相加.java │ │ │ ├── M003_无重复字符的最长子串.java │ │ │ ├── M005_最长回文子串.java │ │ │ ├── M006_Z字形变换.java │ │ │ ├── M011_盛最多水的容器.java │ │ │ ├── M014_最长公共前缀.java │ │ │ ├── M015_三数之和.java │ │ │ ├── M016_最接近的三数之和.java │ │ │ ├── M017_电话号码的字母组合.java │ │ │ ├── M019_删除链表的倒数第N个节点.java │ │ │ ├── M024_两两交换链表中的节点.java │ │ │ ├── M031_下一个排列.java │ │ │ ├── M033_搜索旋转排序数组.java │ │ │ ├── M034_在排序数组中查找元素的第一个和最后一个位置.java │ │ │ ├── M039_组合总和.java │ │ │ ├── M040_组合总和2.java │ │ │ ├── M043_字符串相乘.java │ │ │ ├── M046_全排列.java │ │ │ ├── M047_全排列2.java │ │ │ ├── M056_合并区间.java │ │ │ ├── M060_第k个排列.java │ │ │ ├── M061_旋转链表.java │ │ │ ├── M062_不同路径.java │ │ │ ├── M063_不同路径2.java │ │ │ ├── M064_最小路径和.java │ │ │ ├── M071_简化路径.java │ │ │ ├── M074_搜索二维矩阵.java │ │ │ ├── M077_组合.java │ │ │ ├── M092_反转链表2.java │ │ │ ├── M093_复原IP地址.java │ │ │ ├── M094_二叉树的中序遍历.java │ │ │ ├── M096_不同的二叉搜索树的数量.java │ │ │ └── M098_验证二叉搜索树.java │ │ ├── code100 │ │ │ ├── E101_对称二叉树.java │ │ │ ├── E104_二叉树的最大深度.java │ │ │ ├── E110_平衡二叉树.java │ │ │ ├── E111_二叉树的最小深度.java │ │ │ ├── E121_买卖股票的最佳时机.java │ │ │ ├── E122_买卖股票的最佳时机2.java │ │ │ ├── E198_打家劫舍.java │ │ │ ├── H123_买卖股票的最佳时机3.java │ │ │ ├── H124_二叉树中的最大路径和.java │ │ │ ├── H128_最长连续序列.java │ │ │ ├── H140_单词拆分2.java │ │ │ ├── H164_最大间距.java │ │ │ ├── H188_买卖股票的最佳时机4.java │ │ │ ├── M102_二叉树的层次遍历.java │ │ │ ├── M127_单词接龙.java │ │ │ ├── M134_加油站.java │ │ │ ├── M139_单词拆分.java │ │ │ ├── M144_二叉树的前序遍历.java │ │ │ ├── M145_二叉树的后序遍历.java │ │ │ ├── M146_LRU缓存机制.java │ │ │ ├── M147_对链表进行插入排序.java │ │ │ ├── M148_排序链表.java │ │ │ ├── M151_翻转字符串里的单词.java │ │ │ ├── M153_寻找旋转排序数组中的最小值.java │ │ │ └── M199_二叉树的右视图.java │ │ ├── code1000 │ │ │ ├── E1030_距离顺序排列矩阵单元格.java │ │ │ └── E1071_字符串的最大公因子.java │ │ ├── code1100 │ │ │ ├── E1122_数组的相对排序.java │ │ │ └── E1160_拼写单词.java │ │ ├── code200 │ │ │ ├── E206_反转链表.java │ │ │ ├── E226_翻转二叉树.java │ │ │ ├── E234_回文链表.java │ │ │ ├── E237_删除链表中的结点.java │ │ │ ├── E242_有效的字母异位词.java │ │ │ ├── E283_移动零.java │ │ │ ├── H239_滑动窗口最大值.java │ │ │ ├── H297_二叉树的序列化与反序列化.java │ │ │ ├── M200_岛屿数量.java │ │ │ ├── M207_课程表.java │ │ │ ├── M210_课程表2.java │ │ │ ├── M213_打家劫舍2.java │ │ │ ├── M215_数组中的第K个最大元素.java │ │ │ ├── M216_组合总和3.java │ │ │ └── M222_完全二叉树的节点个数.java │ │ ├── code300 │ │ │ ├── H327_区间和的个数.java │ │ │ ├── H329_矩阵中的最长递增路径.java │ │ │ ├── M300_最长上升子序列.java │ │ │ ├── M309_最佳买卖股票时机含冷冻期.java │ │ │ ├── M322_零钱兑换.java │ │ │ ├── M328_奇偶链表.java │ │ │ ├── M337_打家劫舍3.java │ │ │ ├── M365_水壶问题.java │ │ │ └── M377_组合总和4.java │ │ ├── code400 │ │ │ ├── E409_最长回文串.java │ │ │ ├── E448_找到所有数组中消失的数字.java │ │ │ ├── E496_下一个更大元素1.java │ │ │ ├── H460_LFU缓存.java │ │ │ ├── M402_移掉K位数字.java │ │ │ ├── M406_根据身高重建队列.java │ │ │ ├── M416_分割等和子集.java │ │ │ ├── M452_用最少数量的箭引爆气球.java │ │ │ ├── M474_一和零.java │ │ │ └── M494_目标和.java │ │ ├── code500 │ │ │ ├── H514_自由之路.java │ │ │ ├── M503_下一个更大元素2.java │ │ │ ├── M516_最长回文子序列.java │ │ │ ├── M518_零钱兑换2.java │ │ │ ├── M547_朋友圈.java │ │ │ ├── M547_省份数量.java │ │ │ ├── M560_和为K的子数组.java │ │ │ └── M567_字符串的排列.java │ │ ├── code600 │ │ │ ├── E674_最长连续递增序列.java │ │ │ ├── H679_24点游戏.java │ │ │ ├── M647_回文子串.java │ │ │ └── M695_岛屿的最大面积.java │ │ ├── code700 │ │ │ ├── E704_二分查找.java │ │ │ ├── M714_买卖股票的最佳时机含手续费.java │ │ │ └── M739_每日温度.java │ │ ├── code800 │ │ │ ├── E836_矩形重叠.java │ │ │ ├── E876_链表的中间结点.java │ │ │ └── H887_鸡蛋掉落.java │ │ ├── code900 │ │ │ ├── E905_按奇偶排序数组.java │ │ │ ├── E922_按奇偶排序数组2.java │ │ │ ├── H980_不同路径3.java │ │ │ ├── M912_排序数组.java │ │ │ ├── M945_使数组唯一的最小增量.java │ │ │ └── M973_最接近原点的K个点.java │ │ └── 动态规划 │ │ │ ├── 股票买卖问题.md │ │ │ └── 背包问题.md │ ├── README.md │ ├── SwordOffer │ │ ├── README.md │ │ ├── old │ │ │ ├── b02_单例模式.java │ │ │ ├── b03_二维数组中的二分查找.java │ │ │ ├── b04_替换空格.java │ │ │ ├── b05_从尾到头打印链表.java │ │ │ ├── b06_重建二叉树.java │ │ │ ├── b07_用两个栈实现队列.java │ │ │ ├── b08_旋转数组中二分查找最小数字.java │ │ │ ├── b09_斐波那契数列.java │ │ │ ├── b10_二进制中1的个数.java │ │ │ ├── c11_数值的整数次方.java │ │ │ ├── c12_打印1到最大的n位数.java │ │ │ ├── c13_删除链表结点.java │ │ │ ├── c14_调整数组顺序使奇数位于偶数前面.java │ │ │ ├── c15_链表中倒数第k个结点.java │ │ │ ├── c16_反转链表.java │ │ │ ├── c17_合并两个排序的链表.java │ │ │ ├── c18_树的子结构.java │ │ │ ├── d19_二叉树的镜像.java │ │ │ ├── d20_顺时针打印矩阵.java │ │ │ ├── d21_包含min函数的栈.java │ │ │ ├── d22_栈的压入$弹出序列.java │ │ │ ├── d23_从上往下打印二叉树.java │ │ │ ├── d24_二叉搜索树的后序遍历序列.java │ │ │ ├── d25_二叉树中和为某一值的路径.java │ │ │ ├── d26_复杂链表的复制.java │ │ │ ├── d27_二叉搜索树与双向链表.java │ │ │ ├── d28_字符串的排列.java │ │ │ ├── d28_字符串的组合.java │ │ │ ├── e29_数组中出现次数超过一半的数字.java │ │ │ ├── e30_最小的k个数.java │ │ │ ├── e31_连续子数组的最大和.java │ │ │ ├── e32_从1到n整数中1出现的次数.java │ │ │ ├── e33_把数组排成最小的数.java │ │ │ ├── e34_丑数.java │ │ │ ├── e35_第一个只出现一次的字符.java │ │ │ ├── e36_数组中的逆序对.java │ │ │ ├── e37_两个单向链表的第一个公共结点.java │ │ │ ├── f38_数字在排序数组中出现的次数.java │ │ │ ├── f39_1$二叉树的深度.java │ │ │ ├── f39_2$判断二叉树是否平衡.java │ │ │ ├── f40_数组中只出现一次的数字.java │ │ │ ├── f41_1$和为s的两个数字.java │ │ │ ├── f41_2$和为s的连续正数序列.java │ │ │ ├── f42_1$翻转单词顺序.java │ │ │ ├── f42_2$左旋转字符串.java │ │ │ ├── f43_n个骰子的点数.java │ │ │ ├── f44_扑克牌的顺子.java │ │ │ ├── f45_圆圈中最后剩下的数字$约瑟夫环杀人.java │ │ │ ├── f46_求1到n的和.java │ │ │ ├── f47_不用加减乘除做加法.java │ │ │ ├── f48_不能被继承的类.java │ │ │ ├── g49_把字符串转换成整数.java │ │ │ ├── g50_树中两个结点的最低公共祖先.java │ │ │ ├── h51_数组中重复的数字.java │ │ │ ├── h52_构建乘积数组.java │ │ │ ├── h53_正则表达式匹配.java │ │ │ ├── h54_表示数值的字符串.java │ │ │ ├── h55_字符流中第一个不重复的字符.java │ │ │ ├── h56_链表中环的入口结点.java │ │ │ ├── h57_删除链表中重复的结点.java │ │ │ ├── h58_二叉树的下一个结点.java │ │ │ ├── h59_对称的二叉树.java │ │ │ ├── h60_把二叉树打印成多行.java │ │ │ ├── h61_按之字形顺序打印二叉树.java │ │ │ ├── h62_序列化二叉树.java │ │ │ ├── h63_二叉搜索树的第k个结点.java │ │ │ ├── h64_数据流中的中位数.java │ │ │ ├── h65_滑动窗口的最大值.java │ │ │ ├── h66_矩阵中的路径.java │ │ │ └── h67_机器人的运动范围.java │ │ └── 树 │ │ │ ├── MorrisTraversal.java │ │ │ ├── b06_根据先序和中序数组_重建二叉树.java │ │ │ └── b06_根据后序和中序数组_重建二叉树.java │ ├── a_Sorting │ │ ├── README.md │ │ ├── a_Bubble.java │ │ ├── a_Selection.java │ │ ├── b_Insertion.java │ │ ├── c_Shell.java │ │ ├── d_Merge.java │ │ ├── e_Quick.java │ │ ├── f_Heap.java │ │ ├── g_基数排序.java │ │ └── g_计数排序_桶排序.java │ └── nowcoder │ │ ├── AlgorithmPrototype │ │ ├── SlidingWindowMaxValue.java │ │ └── SubArrayMaxSum.java │ │ ├── a_1st_Season │ │ └── aa_Manacher_bfprt_KMP │ │ │ ├── KMP.java │ │ │ ├── KMP算法.md │ │ │ ├── Manacher.java │ │ │ ├── Manacher算法.md │ │ │ └── README.md │ │ ├── b_2nd_Season │ │ ├── ba160720 │ │ │ ├── README.md │ │ │ ├── RussianDollEnvelopes.java │ │ │ ├── TrappingRainWater.java │ │ │ └── arrUp.java │ │ ├── bb160727 │ │ │ ├── README.md │ │ │ ├── a_SubArrayMaxSum.java │ │ │ ├── b_TwoSubArrayMaxSum.java │ │ │ └── c_MaxLength.java │ │ ├── bc160803 │ │ │ ├── README.md │ │ │ └── src │ │ │ │ ├── CompleteTreeNodeNumber.java │ │ │ │ ├── LongestLessSumSubArrayLength.java │ │ │ │ ├── MaxSubMatrixSumLessK.java │ │ │ │ ├── MaximalRectangle.java │ │ │ │ ├── PrefixCheck.java │ │ │ │ ├── SubArrayMaxSum.java │ │ │ │ └── SubMatrixMaxSum.java │ │ ├── bd160810 │ │ │ ├── README.md │ │ │ ├── SlidingWindowMaxValue.java │ │ │ └── src │ │ │ │ ├── ExpressionCompute.java │ │ │ │ ├── GetMinStack.java │ │ │ │ ├── ReverseStackUsingRecursive.java │ │ │ │ ├── SlidingWindowMaxArray.java │ │ │ │ ├── TwoQueuesImplementStack.java │ │ │ │ └── TwoStacksImplementQueue.java │ │ ├── be160817 │ │ │ ├── README.md │ │ │ └── src │ │ │ │ ├── AllLessNumSubArray.java │ │ │ │ ├── DogCat.java │ │ │ │ ├── Hanoi.java │ │ │ │ └── MaxTree.java │ │ ├── bf160824 │ │ │ ├── README.md │ │ │ └── src │ │ │ │ ├── CopyListWithRandom.java │ │ │ │ ├── FindFirstIntersectNode.java │ │ │ │ ├── IsPalindromeList.java │ │ │ │ ├── Josephus.java │ │ │ │ └── RemoveNodeWired.java │ │ ├── bg160831 │ │ │ ├── README.md │ │ │ └── src │ │ │ │ ├── BSTtoDoubleLinkedList.java │ │ │ │ ├── KMPAlgorithm.java │ │ │ │ └── LongestSubarrayLessSumAwesomeSolution.java │ │ ├── bh160907 │ │ │ ├── BiggestSubBSTInTree.java │ │ │ ├── PreInPosTraversal.java │ │ │ ├── README.md │ │ │ └── src │ │ │ │ ├── Problem_01_PreInPosTraversal.java │ │ │ │ ├── Problem_03_PrintBinaryTree.java │ │ │ │ ├── Problem_06_LongestPathSum.java │ │ │ │ ├── Problem_07_BiggestSubBSTInTree.java │ │ │ │ └── Problem_20_MaxDistanceInTree.java │ │ ├── bi160914 │ │ │ ├── BiggestBSTTopologyInTree.java │ │ │ ├── MorrisTraversal.java │ │ │ ├── README.md │ │ │ └── src │ │ │ │ ├── Problem_05_MorrisTraversal.java │ │ │ │ ├── Problem_08_BiggestBSTTopologyInTree.java │ │ │ │ └── Problem_17_DescendantNode.java │ │ ├── bj160928 │ │ │ ├── IsBalancedBinaryTree.java │ │ │ ├── IsCompleteBinaryTree.java │ │ │ ├── IsSearchBinaryTree.java │ │ │ ├── README.md │ │ │ ├── RecoverBST.java │ │ │ ├── src │ │ │ │ ├── Problem_09_PrintBinaryTreeByLevelAndZigZag.java │ │ │ │ ├── Problem_10_RecoverBST.java │ │ │ │ ├── Problem_13_IsBalancedTree.java │ │ │ │ └── Problem_15_IsBSTAndCBT.java │ │ │ └── testRecoverBST.java │ │ └── bk161012 │ │ │ └── README.md │ │ ├── book │ │ └── BinaryTree │ │ │ └── getPosArray.java │ │ └── image │ │ ├── KMP-1.png │ │ ├── Manacher算法-1.png │ │ ├── Manacher算法-2.png │ │ ├── nowcoderbb16072701.png │ │ ├── nowcoderbb16072702.png │ │ ├── nowcoderbc16080301.png │ │ ├── nowcoderbc16080302.png │ │ ├── nowcoderbc16080303.png │ │ ├── nowcoderbd16081001.png │ │ ├── nowcoderbf16082401.png │ │ ├── nowcoderbf16082402.png │ │ ├── nowcoderbi16091401.png │ │ ├── nowcoderbj16092801.png │ │ ├── nowcoderbj16092802.png │ │ ├── nowcoderbk16101201.png │ │ ├── nowcoderbk16101202.png │ │ ├── nowcoderbk16101203.png │ │ └── nowcoderbk16101204.png │ ├── common │ ├── CommonConstants.java │ ├── datastruct │ │ ├── BinarySearch.java │ │ ├── BinaryTreeNode.java │ │ ├── BinaryTreeNodeWithParent.java │ │ ├── ListNode.java │ │ ├── Node.java │ │ └── TreeNode.java │ ├── enums │ │ └── ErrorCode.java │ ├── model │ │ ├── Person.java │ │ └── PersonDTO.java │ └── util │ │ ├── AssertUtils.java │ │ ├── CommonBeanUtil.java │ │ ├── CompareUtils.java │ │ ├── ConstructLinkedNode.java │ │ ├── ConvertUtils.java │ │ ├── CopyUtil.java │ │ ├── DownloadUtil.java │ │ ├── GenerateUUID.java │ │ ├── LogUtil.java │ │ ├── README.md │ │ ├── StandardInit.java │ │ ├── SwapUtil.java │ │ ├── SysOut.java │ │ ├── SysRandom.java │ │ ├── SystemUtil.java │ │ ├── batchInsert │ │ ├── NameUtil.java │ │ └── RandomValue.java │ │ └── binaryTree │ │ ├── ConstructBinaryTree.java │ │ ├── PrintBinaryTree.java │ │ ├── SerializeAndReConstructTree.java │ │ ├── SerializeAndReConstructTreeImpl.java │ │ └── SerializeAndReConstructTreeUtils.java │ ├── data_struct │ ├── Node.java │ ├── README.md │ ├── ds1_堆 │ │ ├── Heap.java │ │ ├── HeapGreater.java │ │ └── MyHeap.java │ ├── ds2_树 │ │ ├── 二叉查找树 │ │ │ ├── BinarySearchTree.java │ │ │ ├── BinarySearchTreeImpl.java │ │ │ ├── BinarySearchTreeNode.java │ │ │ └── BinarySearchTreeTest.java │ │ └── 平衡查找树 │ │ │ ├── AVLNode.java │ │ │ ├── AVLTree.java │ │ │ ├── AVLTreeImpl.java │ │ │ ├── AVLTreeTest.java │ │ │ ├── RedBlackNode.java │ │ │ ├── RedBlackTree.java │ │ │ ├── RedBlackTreeImpl.java │ │ │ └── RedBlackTreeTest.java │ ├── ds3_并查集 │ │ ├── MyUnionFind.java │ │ └── UnionFind.java │ └── ds4_图 │ │ ├── Edge.java │ │ ├── Graph.java │ │ ├── GraphGenerator.java │ │ ├── Node.java │ │ └── adjoin_map │ │ ├── BFS.java │ │ ├── DFS.java │ │ └── Graph.java │ └── demo │ ├── hessian │ ├── HessianDemo.java │ ├── README.md │ └── 序列化结果对比 │ │ ├── Main.java │ │ └── Student.java │ ├── java │ ├── IO │ │ ├── 1.txt │ │ ├── FileReaderTest.java │ │ └── classpath │ │ │ ├── Main.java │ │ │ ├── ResourcesReaderUtil.java │ │ │ └── RpcConfig.java │ ├── proxy │ │ ├── README.md │ │ ├── cglib │ │ │ ├── Main.java │ │ │ ├── Person.java │ │ │ ├── TargetInterceptor.java │ │ │ ├── TargetMethodCallbackFilter.java │ │ │ ├── TargetResultFixed.java │ │ │ └── lazyloader │ │ │ │ ├── ConcreteClassDispatcher.java │ │ │ │ ├── ConcreteClassLazyLoader.java │ │ │ │ ├── LazyBean.java │ │ │ │ └── PropertyBean.java │ │ └── jdk │ │ │ ├── Calculator.java │ │ │ ├── CalculatorImpl.java │ │ │ ├── HelloService.java │ │ │ ├── HelloServiceImpl.java │ │ │ ├── 动态代理 │ │ │ ├── DynamicProxy.java │ │ │ ├── Main.java │ │ │ └── handler │ │ │ │ ├── LogHandler.java │ │ │ │ └── MyInvocationHandler.java │ │ │ └── 静态代理 │ │ │ ├── HelloServiceProxy.java │ │ │ └── Main.java │ ├── spi │ │ ├── README.md │ │ ├── dubboSPI │ │ │ ├── DistributedArchitecture.java │ │ │ ├── Main_Dubbo_SPI.java │ │ │ └── impl │ │ │ │ ├── DubboImpl.java │ │ │ │ ├── ServiceMeshImpl.java │ │ │ │ └── SpringCloudImpl.java │ │ ├── javaSPI │ │ │ ├── JdbcDemo.java │ │ │ ├── Log.java │ │ │ ├── Main_Java_SPI.java │ │ │ └── impl │ │ │ │ ├── Log4jImpl.java │ │ │ │ ├── LogbackImpl.java │ │ │ │ └── Sfl4jImpl.java │ │ └── springSPI │ │ │ ├── Main_Spring_SPI.java │ │ │ ├── SpringApplicationContextInitializer.java │ │ │ ├── SpringXXXListener.java │ │ │ └── impl │ │ │ ├── SpringXXXListenerImpl01.java │ │ │ └── SpringXXXListenerImpl02.java │ ├── 反射 │ │ ├── CompareUtil.java │ │ └── Main.java │ ├── 基本数据类型 │ │ ├── BigDecimalTest.java │ │ ├── BooleanTest.java │ │ ├── ByteTest.java │ │ ├── DoubleTest.java │ │ ├── IntegerTest.java │ │ ├── MathTest.java │ │ └── StringTest.java │ ├── 并发 │ │ ├── AQS源码阅读 │ │ │ ├── LockAndAqs.java │ │ │ ├── ReentrantLock可重入锁_公平锁.md │ │ │ ├── ReentrantLock可重入锁_非公平锁.md │ │ │ └── synchronized不可重入锁_非公平锁.md │ │ ├── JUC │ │ │ ├── JUC_AQS │ │ │ │ ├── CountdownLatchExample.java │ │ │ │ ├── CyclicBarrierExample.java │ │ │ │ ├── README.md │ │ │ │ ├── SemaphoreExample.java │ │ │ │ └── mylock │ │ │ │ │ ├── MyLock.java │ │ │ │ │ └── MyLockTest.java │ │ │ ├── JUC_demo │ │ │ │ ├── BlockedQueue.java │ │ │ │ ├── Cache.java │ │ │ │ ├── DisruptorDemo.java │ │ │ │ ├── ObjectPool.java │ │ │ │ └── Point.java │ │ │ ├── JUC_other │ │ │ │ ├── ForkJoinExample.java │ │ │ │ ├── FutureTaskExample.java │ │ │ │ ├── Main.java │ │ │ │ ├── ProducerConsumer.java │ │ │ │ └── README.md │ │ │ └── 可见性.java │ │ ├── Main.java │ │ ├── README.md │ │ ├── thread_demo │ │ │ ├── README.md │ │ │ ├── ThreadDemo1.java │ │ │ ├── ThreadDemo2.java │ │ │ ├── ThreadDemo3.java │ │ │ └── ThreadDemo4.java │ │ ├── threadpool │ │ │ ├── ExecutorsExceptionTest.java │ │ │ ├── Main.java │ │ │ ├── a0_多线程同步.java │ │ │ ├── a1_MyThreadPool.java │ │ │ ├── a2_FutureTask.java │ │ │ ├── b1_FutureTaskDemo.java │ │ │ ├── b2_CompletableFutureDemo.java │ │ │ ├── b2_CompletableFutureDemo2.java │ │ │ ├── b3_CompletionServiceDemo.java │ │ │ ├── c1_FockJoinDemo.java │ │ │ ├── c2_FockJoinDemo2.java │ │ │ └── 让3个线程顺序执行 │ │ │ │ ├── OddEvenPrint.java │ │ │ │ ├── aThreadJoinDemo.java │ │ │ │ ├── bThreadMainJoinDemo.java │ │ │ │ ├── cThreadWaitNotifyDemo.java │ │ │ │ ├── dThreadAwaitSingalDemo.java │ │ │ │ ├── eSingleThreadPoolDemo.java │ │ │ │ ├── fCountDownLatchDemo.java │ │ │ │ └── gCyclicBarrierDemo.java │ │ └── 悲观锁vs乐观锁 │ │ │ ├── CAS │ │ │ ├── AtomicIntegerExample.java │ │ │ └── AtomicReferenceExample.java │ │ │ ├── README.md │ │ │ ├── reentrantLock │ │ │ ├── LockExample.java │ │ │ ├── Main.java │ │ │ └── 线程间的协作 │ │ │ │ ├── AwaitSignalExample.java │ │ │ │ ├── JoinExample.java │ │ │ │ ├── Main.java │ │ │ │ ├── README.md │ │ │ │ └── WaitNotifyExample.java │ │ │ └── synchronize │ │ │ ├── Main.java │ │ │ └── SynchronizedExample.java │ ├── 异常 │ │ ├── Main.java │ │ └── README.md │ ├── 继承 │ │ ├── HelloA.java │ │ └── HelloB.java │ └── 集合 │ │ ├── List类.java │ │ ├── Map类.java │ │ └── Set类.java │ ├── jvm │ ├── GCRoots │ │ ├── GCRootsTest01.java │ │ ├── GCRootsTest02.java │ │ ├── GCRootsTest03.java │ │ ├── GCRootsTest04.java │ │ └── README.md │ ├── GC优化 │ │ └── HeapOOM.java │ ├── classloader │ │ ├── ClassLoaderDemo.java │ │ ├── LoadStringDemo.java │ │ └── 自定义类加载器 │ │ │ ├── LoadDemo.java │ │ │ ├── Main.java │ │ │ └── MyClassLoader.java │ └── 引用 │ │ └── Reference.java │ ├── netty │ ├── Main.java │ ├── README.md │ ├── http │ │ ├── App.java │ │ ├── HttpServer.java │ │ ├── ServerHandler.java │ │ └── ServerInitializer.java │ ├── rpc │ │ ├── ClientApp.java │ │ ├── ServerApp.java │ │ ├── client │ │ │ ├── RPCClient.java │ │ │ └── request │ │ │ │ ├── RPCException.java │ │ │ │ ├── RPCRequest.java │ │ │ │ ├── RPCResponse.java │ │ │ │ ├── RequestId.java │ │ │ │ └── ResponseRegistry.java │ │ ├── customHandler │ │ │ ├── ExpRequest.java │ │ │ ├── ExpRequestHandler.java │ │ │ ├── ExpResponse.java │ │ │ └── FibRequestHandler.java │ │ └── server │ │ │ ├── RPCServer.java │ │ │ ├── ServerHandler.java │ │ │ └── message │ │ │ ├── DefaultHandler.java │ │ │ ├── IMessageHandler.java │ │ │ ├── MessageHandlers.java │ │ │ ├── MessageInput.java │ │ │ ├── MessageOutput.java │ │ │ └── MessageRegistry.java │ └── webSocket │ │ ├── client │ │ ├── ClientApp.java │ │ ├── ClientHandler.java │ │ ├── ClientInitializer.java │ │ └── SocketClient.java │ │ └── server │ │ ├── ServerApp.java │ │ ├── ServerHandler.java │ │ ├── ServerInitializer.java │ │ └── SocketServer.java │ └── redis │ ├── HyperLogLog │ ├── HyperLogLogCounting.java │ └── HyperLogLogCountingDemo.java │ └── RateLimiter │ ├── README.md │ └── RedisRateLimiter.java ├── resources ├── META-INF │ ├── dubbo │ │ └── internal │ │ │ └── cc.tianbin.demo.java.spi.dubboSPI.DistributedArchitecture │ ├── services │ │ └── cc.tianbin.demo.java.spi.javaSPI.Log │ └── spring.factories ├── config │ └── rpc_config.json ├── data │ └── graph │ │ ├── characterGraphfilePath.txt │ │ ├── digitGraph.txt │ │ ├── mediumG.txt │ │ ├── tinyCG.txt │ │ ├── tinyDG.txt │ │ ├── tinyDG2.txt │ │ ├── tinyEWG.txt │ │ └── tinyG.txt ├── image │ └── stock_buy_sell.png ├── properties │ └── default.properties └── redis │ └── lua │ └── RedLimiter.lua └── test └── cc └── tianbin ├── UnitTestDemo.java ├── algorithm_practice ├── TempTest.java ├── 二分查找.java ├── 堆排序.java └── 快速排序.java ├── algorithmzuo ├── README.md ├── b_体系学习班 │ ├── README.md │ ├── c0101_排序 │ │ ├── Code01_SelectionSort.java │ │ ├── Code02_BubbleSort.java │ │ ├── Code03_InsertionSort.java │ │ ├── Code04_1_MergeSort_Recursion.java │ │ ├── Code04_2_MergeSort_Non_Recursion.java │ │ ├── Code04_3_SmallSum.java │ │ ├── Code04_4_ReversePair.java │ │ ├── Code04_5_BiggerThanRightTwice.java │ │ ├── Code04_6_CountOfRangeSum.java │ │ ├── Code05_1_PartitionAndQuickSort.java │ │ ├── Code05_2_QuickSortRecursionAndUnrecursion.java │ │ ├── Code06_1_HeapSort.java │ │ ├── Code06_2_SortArrayDistanceLessK.java │ │ ├── Code06_3_CoverMax.java │ │ ├── Code07_CountSort.java │ │ └── Code08_RadixSort.java │ ├── c0102_二分查找 │ │ ├── Code01_BSExist.java │ │ ├── Code02_BSNearLeft.java │ │ ├── Code03_BSNearRight.java │ │ └── Code04_BSAwesome.java │ ├── c0103_异或运算 │ │ ├── Code01_Swap.java │ │ ├── Code02_EvenTimesOddTimes.java │ │ └── Code03_KM.java │ ├── c0105_栈和队列 │ │ ├── Code03_DoubleEndsQueueToStackAndQueue.java │ │ ├── Code04_RingArray.java │ │ ├── Code05_GetMinStack.java │ │ ├── Code06_TwoStacksImplementQueue.java │ │ └── Code07_TwoQueueImplementStack.java │ ├── c01xx_一些超级基础的算法.md │ ├── c0201_链表 │ │ ├── Code01_1_ReverseListNode.java │ │ ├── Code01_2_ReverseDoubleListNode.java │ │ ├── Code02_DeleteGivenValue.java │ │ ├── Code03_LinkedListMid.java │ │ ├── Code04_IsPalindromeList.java │ │ ├── Code05_SmallerEqualBigger.java │ │ ├── Code06_CopyListWithRandom.java │ │ └── Code07_FindFirstIntersectListNode.java │ ├── c0202_前缀树 │ │ └── Code01_TrieTree.java │ ├── c0203_树 │ │ ├── Code01_RecursiveTraversalBT.java │ │ ├── Code02_UnRecursiveTraversalBT.java │ │ ├── Code03_LevelTraversalBT.java │ │ ├── Code05_EncodeNaryTreeToBinaryTree.java │ │ └── Code06_TreeMaxWidth.java │ ├── c0204_树型DP │ │ ├── Code01_IsBalanced.java │ │ ├── Code02_IsBST.java │ │ ├── Code03_MaxDistance.java │ │ ├── Code04_IsFull.java │ │ ├── Code05_MaxSubBSTSize.java │ │ ├── Code06_IsCBT.java │ │ ├── Code07_MaxSubBSTHead.java │ │ ├── Code08_lowestAncestor.java │ │ └── Code09_MaxHappy.java │ ├── c02xx_链表和树.md │ ├── c0300_贪心 │ │ ├── Code01_Light.java │ │ ├── Code02_LessMoneySplitGold.java │ │ ├── Code03_BestArrange.java │ │ └── Code04_IPO.java │ ├── c03xx_贪心算法.md │ ├── c0400_并查集 │ │ └── Code02_NumberOfIslands.java │ ├── c04xx_并查集.md │ ├── c0500_图.md │ ├── c0500_图 │ │ ├── Code01_BFS.java │ │ ├── Code02_DFS.java │ │ ├── Code03_1_TopologySort.java │ │ ├── Code03_2_TopologicalOrderBFS.java │ │ ├── Code03_3_TopologicalOrderDFS.java │ │ ├── Code04_Kruskal.java │ │ ├── Code05_Prim.java │ │ ├── Code06_1_Dijkstra.java │ │ ├── Code06_2_Dijkstra.java │ │ └── Code07_NetworkDelayTime.java │ ├── c0600_常见的递归.md │ ├── c0600_常见的递归 │ │ ├── Code01_Hanoi.java │ │ ├── Code02_PrintAllSubSequences.java │ │ ├── Code03_PrintAllPermutations.java │ │ └── Code04_ReverseStackUsingRecursive.java │ ├── c0700_动态规划.md │ └── c0700_动态规划 │ │ ├── Code01_RobotWalk.java │ │ ├── Code02_CardsInLine.java │ │ ├── Code03_Knapsack.java │ │ ├── Code04_ConvertToLetterString.java │ │ ├── Code05_StickersToSpellWord.java │ │ ├── Code06_LongestCommonSubsequence.java │ │ ├── Code07_PalindromeSubsequence.java │ │ ├── Code08_HorseJump.java │ │ ├── Code09_Coffee.java │ │ ├── Code10_MinPathSum.java │ │ ├── Code11_CoinsWayEveryPaperDifferent.java │ │ ├── Code12_CoinsWayNoLimit.java │ │ ├── Code13_CoinsWaySameValueSamePapper.java │ │ ├── Code14_MinCoinsNoLimit.java │ │ ├── Code15_BobDie.java │ │ ├── Code16_KillMonster.java │ │ ├── Code17_SplitNumber.java │ │ ├── Code18_SplitSumClosed.java │ │ ├── Code19_SplitSumClosedSizeHalf.java │ │ └── Code20_NQueens.java └── c_大厂刷题班 │ └── README.md ├── common └── util │ ├── DateTimeUtilTest.java │ ├── ExcelReadUtilsTest.java │ └── validate │ └── FluentValidatorTest.java ├── demo ├── Main.java ├── java │ ├── ObjectTest.java │ ├── OptionalTest.java │ ├── SwitchCaseTest.java │ ├── spring │ │ └── SpringTest.java │ ├── 反射 │ │ ├── CommonBeanUtilTest.java │ │ ├── CopyProperties_性能测试.java │ │ ├── README.md │ │ └── ReflectTest.java │ └── 集合 │ │ ├── ListStreamTest.java │ │ ├── ListTest.java │ │ ├── MapTest.java │ │ └── SetTest.java ├── redis │ └── RateLimiter │ │ └── RedisRateLimiterTest.java └── temp │ └── JsonParseTest.java ├── java ├── lang │ └── test │ │ ├── String.class │ │ └── String_.java └── mybatis │ └── MybatisTest.java ├── javalang └── test │ ├── FinallyTest.java │ └── IfTest.java └── tmp └── interview └── Main.java /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Example user template template 3 | ### Example user template 4 | 5 | # IntelliJ project files 6 | .idea 7 | *.iml 8 | /target 9 | *.DS_Store 10 | .fleet 11 | 12 | -------------------------------------------------------------------------------- /.obsidian/app.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /.obsidian/appearance.json: -------------------------------------------------------------------------------- 1 | { 2 | "accentColor": "" 3 | } -------------------------------------------------------------------------------- /.obsidian/community-plugins.json: -------------------------------------------------------------------------------- 1 | [ 2 | "table-editor-obsidian" 3 | ] -------------------------------------------------------------------------------- /.obsidian/core-plugins-migration.json: -------------------------------------------------------------------------------- 1 | { 2 | "file-explorer": true, 3 | "global-search": true, 4 | "switcher": true, 5 | "graph": true, 6 | "backlink": true, 7 | "outgoing-link": true, 8 | "tag-pane": true, 9 | "page-preview": true, 10 | "daily-notes": true, 11 | "templates": true, 12 | "note-composer": true, 13 | "command-palette": true, 14 | "slash-command": false, 15 | "editor-status": true, 16 | "starred": true, 17 | "markdown-importer": false, 18 | "zk-prefixer": false, 19 | "random-note": false, 20 | "outline": true, 21 | "word-count": true, 22 | "slides": false, 23 | "audio-recorder": false, 24 | "workspaces": false, 25 | "file-recovery": true, 26 | "publish": false, 27 | "sync": false, 28 | "canvas": true 29 | } -------------------------------------------------------------------------------- /.obsidian/core-plugins.json: -------------------------------------------------------------------------------- 1 | [ 2 | "file-explorer", 3 | "global-search", 4 | "switcher", 5 | "graph", 6 | "backlink", 7 | "canvas", 8 | "outgoing-link", 9 | "tag-pane", 10 | "page-preview", 11 | "daily-notes", 12 | "templates", 13 | "note-composer", 14 | "command-palette", 15 | "editor-status", 16 | "starred", 17 | "outline", 18 | "word-count", 19 | "file-recovery" 20 | ] -------------------------------------------------------------------------------- /.obsidian/hotkeys.json: -------------------------------------------------------------------------------- 1 | { 2 | "app:toggle-left-sidebar": [ 3 | { 4 | "modifiers": [], 5 | "key": "F1" 6 | } 7 | ], 8 | "app:toggle-right-sidebar": [ 9 | { 10 | "modifiers": [], 11 | "key": "F4" 12 | } 13 | ], 14 | "editor:set-heading-1": [], 15 | "editor:set-heading-2": [ 16 | { 17 | "modifiers": [ 18 | "Mod" 19 | ], 20 | "key": "2" 21 | } 22 | ], 23 | "editor:set-heading-3": [ 24 | { 25 | "modifiers": [ 26 | "Mod" 27 | ], 28 | "key": "3" 29 | } 30 | ], 31 | "editor:set-heading-4": [ 32 | { 33 | "modifiers": [ 34 | "Mod" 35 | ], 36 | "key": "4" 37 | } 38 | ], 39 | "editor:set-heading": [ 40 | { 41 | "modifiers": [ 42 | "Mod" 43 | ], 44 | "key": "1" 45 | } 46 | ], 47 | "workspace:goto-tab-1": [], 48 | "workspace:goto-tab-2": [], 49 | "workspace:goto-tab-3": [], 50 | "workspace:goto-tab-4": [], 51 | "app:open-help": [], 52 | "table-editor-obsidian:format-all-tables": [ 53 | { 54 | "modifiers": [ 55 | "Alt", 56 | "Mod" 57 | ], 58 | "key": "L" 59 | } 60 | ] 61 | } -------------------------------------------------------------------------------- /.obsidian/plugins/table-editor-obsidian/data.json: -------------------------------------------------------------------------------- 1 | { 2 | "formatType": "normal", 3 | "showRibbonIcon": true, 4 | "bindEnter": true, 5 | "bindTab": true 6 | } -------------------------------------------------------------------------------- /.obsidian/plugins/table-editor-obsidian/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "table-editor-obsidian", 3 | "name": "Advanced Tables", 4 | "author": "Tony Grosinger", 5 | "authorUrl": "https://grosinger.net", 6 | "description": "Improved table navigation, formatting, manipulation, and formulas", 7 | "isDesktopOnly": false, 8 | "minAppVersion": "1.0.0", 9 | "version": "0.18.1", 10 | "js": "main.js", 11 | "donation": "https://buymeacoffee.com/tgrosinger" 12 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 算法 2 | [算法篇](src/main/java/algorithm_practice/README.md) 3 | [数据结构](src/main/java/data_struct/README.md) 4 | 5 | # 操作系统 6 | [jvm](src/main/java/cc/tianbin/jvm) 7 | 8 | # 网络编程 9 | [org.tianbin.netty](src/main/java/cc/tianbin/netty/README.md) -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/Coding_Interview_Guide_2ndEdition/Chapter_01_栈和队列/P01_GetMinStack.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.Coding_Interview_Guide_2ndEdition.Chapter_01_栈和队列; 2 | 3 | import junit.framework.TestCase; 4 | import org.junit.Test; 5 | 6 | import java.util.Stack; 7 | 8 | /* 9 | 设计一个有getMin 功能的栈 10 | 11 | 【题目】 12 | 实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作。 13 | 14 | 【要求】 15 | 1.pop、push、getMin 操作的时间复杂度都是O(1)。 16 | 17 | 2.设计的栈类型可以使用现成的栈结构。 18 | 19 | 【难度】 20 | 士 ★☆☆☆ 21 | */ 22 | public class P01_GetMinStack extends TestCase { 23 | 24 | @Test 25 | public void testCase() { 26 | 27 | } 28 | 29 | class MyStack { 30 | private Stack stackData; 31 | private Stack stackMin; //加一个最小值栈。getMin直接 stackMin.peek() 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/Coding_Interview_Guide_2ndEdition/Chapter_01_栈和队列/P03_使用递归逆序一个栈.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.Coding_Interview_Guide_2ndEdition.Chapter_01_栈和队列; 2 | 3 | import cc.tianbin.common.util.StandardInit; 4 | import cc.tianbin.common.util.SysOut; 5 | import junit.framework.TestCase; 6 | import org.junit.Test; 7 | 8 | import java.util.Stack; 9 | 10 | /* 11 | 【题目】 12 | 一个栈依次压入1、2、3、4、5,那么从栈顶到栈底分别为5、4、3、2、1。将这个栈转置后,从栈顶到栈底为1、2、3、4、5,也就是实现栈中元素的逆序,但是只能用递归函数来实现,不能用其他数据结构。 13 | 14 | 【难度】 15 | 尉 ★★☆☆ 16 | */ 17 | public class P03_使用递归逆序一个栈 extends TestCase { 18 | 19 | @Test 20 | public void testCase() { 21 | Stack stack = StandardInit.initStack(); 22 | reverseStackUsingRecursive(stack); 23 | 24 | SysOut.printStack(stack); 25 | } 26 | 27 | /** 28 | * 设计递归 29 | * @param stack 30 | */ 31 | private void reverseStackUsingRecursive(Stack stack) { 32 | if (stack.isEmpty()) { 33 | return ; 34 | } 35 | Integer lastElement = getStackLastElement(stack); 36 | reverseStackUsingRecursive(stack); 37 | stack.push(lastElement); 38 | } 39 | 40 | private Integer getStackLastElement(Stack stack) { 41 | Integer result = stack.pop(); 42 | if (stack.isEmpty()) { 43 | return result; 44 | } else { 45 | Integer stackLastElement = getStackLastElement(stack); 46 | stack.push(result); 47 | return stackLastElement; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/Coding_Interview_Guide_2ndEdition/Chapter_04_递归和动态规划/P01_斐波那契数列.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.Coding_Interview_Guide_2ndEdition.Chapter_04_递归和动态规划; 2 | 3 | import junit.framework.TestCase; 4 | import org.junit.Test; 5 | 6 | /* 7 | 8 | */ 9 | public class P01_斐波那契数列 extends TestCase { 10 | 11 | @Test 12 | public void testCase() { 13 | // O(2^N) 14 | System.out.println(f1(4)); 15 | 16 | // O(N) 17 | System.out.println(f2(4)); 18 | 19 | // 20 | } 21 | 22 | 23 | 24 | private int f2(int n) { 25 | if (n < 1) { 26 | return 0; 27 | } 28 | 29 | if (n == 1 || n == 2) { 30 | return 1; 31 | } 32 | 33 | int n1 = 1; // n - 1 34 | int n2 = 1; // n - 2 35 | int result = 0; 36 | for (int i = 3; i <= n; i++) { 37 | result = n1 + n2; 38 | n2 = n1; 39 | n1 = result; 40 | } 41 | 42 | return result; 43 | } 44 | 45 | private int f1(int n) { 46 | if (n < 1) { 47 | return 0; 48 | } 49 | 50 | if (n == 1 || n == 2) { 51 | return 1; 52 | } 53 | 54 | return f1(n - 1) + f1(n - 2); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/Coding_Interview_Guide_2ndEdition/README.md: -------------------------------------------------------------------------------- 1 | # [《程序员代码面试指南》](https://book.douban.com/subject/30422021/) 2 | 3 | ## 第一章 栈和队列 4 | 5 | 双端队列: 6 | - [P07_生成窗口最大值数组.java](./Chapter_01_栈和队列/P07_生成窗口最大值数组.java) 7 | - [P10_最大值减去最小值小于或等于num的子数组数量.java](./Chapter_01_栈和队列/P10_最大值减去最小值小于或等于num的子数组数量.java) 8 | 9 | 单调栈结构: 10 | - [P08_单调栈结构.java](./Chapter_01_栈和队列/P08_单调栈结构.java) 11 | - [P09_求最大子矩阵的大小.java](./Chapter_01_栈和队列/P09_求最大子矩阵的大小.java) 12 | - [P11_可见的山峰对数量.java](./Chapter_01_栈和队列/P11_可见的山峰对数量.java) 13 | - [H042_接雨水](../LeetCode/code000/H042_接雨水.java) 14 | 15 | ## 第四章 递归和动态规划 16 | 17 | - [P06_用栈来解决汉诺塔问题.java](./Chapter_01_栈和队列/P06_用栈来解决汉诺塔问题.java) 18 | - [P03_使用递归逆序一个栈.java](./Chapter_01_栈和队列/P03_使用递归逆序一个栈.java) 19 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/LeetCode/code000/E069_x的平方根.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.LeetCode.code000; 2 | 3 | import junit.framework.TestCase; 4 | import org.junit.Test; 5 | 6 | /* 7 | 实现 int sqrt(int x) 函数。 8 | 9 | 计算并返回 x 的平方根,其中 x 是非负整数。 10 | 11 | 由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。 12 | 13 | 示例 1: 14 | 输入: 4 15 | 输出: 2 16 | 17 | 示例 2: 18 | 输入: 8 19 | 输出: 2 20 | 说明: 8 的平方根是 2.82842..., 21 | 由于返回类型是整数,小数部分将被舍去。 22 | 23 | 来源:力扣(LeetCode) 24 | 链接:https://leetcode-cn.com/problems/sqrtx 25 | 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 26 | 27 | * Created by nibnait on 2019-08-07 28 | */ 29 | public class E069_x的平方根 extends TestCase { 30 | 31 | @Test 32 | public void testCase() { 33 | System.out.println(mySqrt(2)); 34 | System.out.println(mySqrt(4)); 35 | System.out.println(mySqrt(8)); 36 | System.out.println(mySqrt(2147395599)); 37 | } 38 | 39 | public int mySqrt(int x) { 40 | 41 | long lo = 0; 42 | long hi = x; 43 | long mid = 0; 44 | while (lo < hi) { 45 | mid = (lo + hi + 1) / 2; 46 | long square = mid * mid; 47 | if (square > x) { 48 | hi = mid - 1; 49 | } else { 50 | lo = mid; 51 | } 52 | } 53 | 54 | return (int) lo; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/LeetCode/code200/M215_数组中的第K个最大元素.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.LeetCode.code200; 2 | 3 | import junit.framework.TestCase; 4 | import org.junit.Test; 5 | 6 | import java.util.Arrays; 7 | 8 | /* 9 | 未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。 10 | 11 | 示例 1: 12 | 13 | 输入: [3,2,1,5,6,4] 和 k = 2 14 | 输出: 5 15 | 示例 2: 16 | 17 | 输入: [3,2,3,1,2,4,5,5,6] 和 k = 4 18 | 输出: 4 19 | 说明: 20 | 21 | 你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。 22 | 23 | 24 | 25 | 来源:力扣(LeetCode) 26 | 链接:https://leetcode-cn.com/problems/kth-largest-element-in-an-array 27 | 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 28 | Created by nibnait on 2020-01-12 29 | */ 30 | public class M215_数组中的第K个最大元素 extends TestCase { 31 | 32 | @Test 33 | public void testCase() { 34 | int[] nums = new int[]{4, 5, 6, 7, 0, 1, 2}; 35 | int k = 4; 36 | System.out.println(findKthLargest(nums, k)); 37 | } 38 | 39 | /** 40 | * 徒手撸个堆排序吧: 41 | */ 42 | public int findKthLargest(int[] nums, int k) { 43 | Arrays.sort(nums); 44 | return nums[nums.length - k]; 45 | } 46 | 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/LeetCode/code200/M222_完全二叉树的节点个数.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.LeetCode.code200; 2 | 3 | import cc.tianbin.common.datastruct.TreeNode; 4 | import cc.tianbin.common.util.binaryTree.ConstructBinaryTree; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | /* 9 | 给出一个完全二叉树,求出该树的节点个数。 10 | 11 | 说明: 12 | 13 | 完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。 14 | 15 | 示例: 16 | 17 | 输入: 18 | 1 19 | / \ 20 | 2 3 21 | / \ / 22 | 4 5 6 23 | 24 | 输出: 6 25 | 26 | 27 | 来源:力扣(LeetCode) 28 | 链接:https://leetcode-cn.com/problems/count-complete-tree-nodes 29 | 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 30 | * Created by nibnait on 2020/11/24 31 | */ 32 | public class M222_完全二叉树的节点个数 { 33 | 34 | @Test 35 | public void testCase() { 36 | TreeNode root = ConstructBinaryTree.constructByBFSArray(new Integer[]{1,2,3,4,5,6}); 37 | int excepted = 6; 38 | Assert.assertEquals(excepted, countNodes(root)); 39 | 40 | root = ConstructBinaryTree.constructByBFSArray(new Integer[]{1,2,3,4,5,6,7}); 41 | excepted = 7; 42 | Assert.assertEquals(excepted, countNodes(root)); 43 | 44 | } 45 | 46 | /** 47 | * dfs 48 | */ 49 | public int countNodes(TreeNode root) { 50 | 51 | if (root == null) { 52 | return 0; 53 | } 54 | 55 | int res = 1; 56 | 57 | res += countNodes(root.left) + countNodes(root.right); 58 | 59 | return res; 60 | } 61 | 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/LeetCode/code400/E409_最长回文串.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.LeetCode.code400; 2 | 3 | import junit.framework.TestCase; 4 | import org.junit.Test; 5 | 6 | import java.util.HashSet; 7 | 8 | /* 9 | 给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串。 10 | 11 | 在构造过程中,请注意区分大小写。比如 "Aa" 不能当做一个回文字符串。 12 | 13 | 注意: 14 | 假设字符串的长度不会超过 1010。 15 | 16 | 示例 1: 17 | 18 | 输入: 19 | "abccccdd" 20 | 21 | 输出: 22 | 7 23 | 24 | 解释: 25 | 我们可以构造的最长的回文串是"dccaccd", 它的长度是 7。 26 | Created by nibnait on 2020-03-19 27 | */ 28 | public class E409_最长回文串 extends TestCase { 29 | 30 | @Test 31 | public void testCase() { 32 | String s = "abccccdd"; 33 | System.out.println(longestPalindrome(s)); 34 | 35 | String s1 = "abccccdd"; 36 | System.out.println(longestPalindrome(s1)); 37 | 38 | 39 | } 40 | 41 | public int longestPalindrome(String s) { 42 | if (s == null) { 43 | return 0; 44 | } 45 | 46 | if (s.length() <= 1) { 47 | return s.length(); 48 | } 49 | 50 | int result = 0; 51 | HashSet set = new HashSet<>(); 52 | for (int i = 0; i < s.length(); i++) { 53 | char ch = s.charAt(i); 54 | if (set.contains(ch)) { 55 | set.remove(ch); 56 | result += 2; 57 | } else { 58 | set.add(ch); 59 | } 60 | } 61 | 62 | if (!set.isEmpty()) { 63 | result += 1; 64 | } 65 | return result; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/LeetCode/code400/M494_目标和.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.LeetCode.code400; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | /* 7 | 给定一个非负整数数组,a1, a2, ..., an, 和一个目标数,S。现在你有两个符号 + 和 -。对于数组中的任意一个整数,你都可以从 + 或 -中选择一个符号添加在前面。 8 | 9 | 返回可以使最终数组和为目标数 S 的所有添加符号的方法数。 10 | 11 | 示例: 12 | 输入:nums: [1, 1, 1, 1, 1], S: 3 13 | 输出:5 14 | 解释: 15 | -1+1+1+1+1 = 3 16 | +1-1+1+1+1 = 3 17 | +1+1-1+1+1 = 3 18 | +1+1+1-1+1 = 3 19 | +1+1+1+1-1 = 3 20 | 一共有5种方法让最终目标和为3。 21 | 22 | 提示: 23 | 数组非空,且长度不会超过 20 。 24 | 初始的数组的和不会超过 1000 。 25 | 保证返回的最终结果能被 32 位整数存下。 26 | 27 | 来源:力扣(LeetCode) 28 | 链接:https://leetcode-cn.com/problems/target-sum 29 | 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 30 | */ 31 | public class M494_目标和 { 32 | 33 | @Test 34 | public void testCase() { 35 | int[] nums = new int[]{1, 1, 1, 1, 1}; 36 | int S = 3; 37 | int excepted = 5; 38 | Assert.assertEquals(excepted, findTargetSumWays(nums, S)); 39 | 40 | 41 | } 42 | 43 | public int findTargetSumWays(int[] nums, int S) { 44 | 45 | // dp[i][j]: 使用 nums[0...i] 个数,使用 + - 凑成 j 的方法数 46 | int[][] dp = new int[nums.length+1][S+1]; 47 | 48 | for (int i = 0; i <= S; i++) { 49 | dp[0][i] = 0; 50 | } 51 | 52 | 53 | 54 | for (int i = 1; i <= nums.length; i++) { 55 | for (int j = 0; j <= S; j++) { 56 | 57 | 58 | 59 | } 60 | } 61 | 62 | return dp[nums.length][S]; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/LeetCode/code900/E905_按奇偶排序数组.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.LeetCode.code900; 2 | 3 | import org.junit.Test; 4 | 5 | /* 6 | 给定一个非负整数数组 A,返回一个数组,在该数组中, A 的所有偶数元素之后跟着所有奇数元素。 7 | 8 | 你可以返回满足此条件的任何数组作为答案。 9 | 10 | 11 | 12 | 示例: 13 | 14 | 输入:[3,1,2,4] 15 | 输出:[2,4,3,1] 16 | 输出 [4,2,3,1],[2,4,1,3] 和 [4,2,1,3] 也会被接受。 17 | 18 | 19 | 提示: 20 | 21 | 1 <= A.length <= 5000 22 | 0 <= A[i] <= 5000 23 | 24 | 25 | 来源:力扣(LeetCode) 26 | 链接:https://leetcode-cn.com/problems/sort-array-by-parity 27 | 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 28 | * Created by nibnait on 2020/11/12 29 | */ 30 | public class E905_按奇偶排序数组 { 31 | 32 | public int[] sortArrayByParity(int[] A) { 33 | 34 | int p1 = 0; 35 | int p2 = A.length-1; 36 | 37 | while (p1 < p2) { 38 | if (A[p1] % 2 == 0) { 39 | p1++; 40 | } else { 41 | swap(A, p1, p2); 42 | p2--; 43 | } 44 | } 45 | 46 | return A; 47 | } 48 | 49 | private void swap(int[] A, int p1, int p2) { 50 | int temp = A[p1]; 51 | A[p1] = A[p2]; 52 | A[p2] = temp; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/LeetCode/code900/E922_按奇偶排序数组2.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.LeetCode.code900; 2 | 3 | /* 4 | 给定一个非负整数数组 A, A 中一半整数是奇数,一半整数是偶数。 5 | 6 | 对数组进行排序,以便当 A[i] 为奇数时,i 也是奇数;当 A[i] 为偶数时, i 也是偶数。 7 | 8 | 你可以返回任何满足上述条件的数组作为答案。 9 | 10 | 11 | 12 | 示例: 13 | 14 | 输入:[4,2,5,7] 15 | 输出:[4,5,2,7] 16 | 解释:[4,7,2,5],[2,5,4,7],[2,7,4,5] 也会被接受。 17 | 18 | 19 | 提示: 20 | 21 | 2 <= A.length <= 20000 22 | A.length % 2 == 0 23 | 0 <= A[i] <= 1000 24 | 25 | 26 | 来源:力扣(LeetCode) 27 | 链接:https://leetcode-cn.com/problems/sort-array-by-parity-ii 28 | 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 29 | * Created by nibnait on 2020/11/12 30 | */ 31 | public class E922_按奇偶排序数组2 { 32 | 33 | public int[] sortArrayByParityII(int[] A) { 34 | 35 | int p1 = 0; 36 | int p2 = 1; 37 | 38 | while (p1 < A.length && p2 < A.length) { 39 | if (A[p1] % 2 == 0) { 40 | p1 += 2; 41 | } else { 42 | // 找到一个偶数 与其交换 43 | while (p2 < A.length) { 44 | if (A[p2] % 2 == 0) { 45 | swap(A, p1, p2); 46 | break; 47 | } else { 48 | p2 += 2; 49 | } 50 | } 51 | p1 += 2; 52 | } 53 | } 54 | 55 | return A; 56 | } 57 | 58 | private void swap(int[] A, int p1, int p2) { 59 | int temp = A[p1]; 60 | A[p1] = A[p2]; 61 | A[p2] = temp; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/LeetCode/code900/M912_排序数组.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.LeetCode.code900; 2 | 3 | import junit.framework.TestCase; 4 | import org.junit.Test; 5 | 6 | /* 7 | 给你一个整数数组 nums,请你将该数组升序排列。 8 | 9 | 10 | 11 | 示例 1: 12 | 13 | 输入:nums = [5,2,3,1] 14 | 输出:[1,2,3,5] 15 | 示例 2: 16 | 17 | 输入:nums = [5,1,1,2,0,0] 18 | 输出:[0,0,1,1,2,5] 19 | 20 | 21 | 提示: 22 | 23 | 1 <= nums.length <= 50000 24 | -50000 <= nums[i] <= 50000 25 | 26 | 27 | 来源:力扣(LeetCode) 28 | 链接:https://leetcode-cn.com/problems/sort-an-array 29 | 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 30 | Created by nibnait on 2020-03-31 31 | */ 32 | public class M912_排序数组 extends TestCase { 33 | 34 | @Test 35 | public void testCase() { 36 | 37 | } 38 | 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/LeetCode/动态规划/背包问题.md: -------------------------------------------------------------------------------- 1 | 2 | ## 01背包 3 | - [M416_分割等和子集](../code400/M416_分割等和子集.java) 4 | - [M474_一和零](../code400/M474_一和零.java) 5 | 6 | ## 完全背包 7 | - [M322_零钱兑换](../code300/M322_零钱兑换.java) 8 | 9 | 10 | ## 组合问题 11 | - [M377_组合总和4](../code300/M377_组合总和4.java) 12 | - [M518_零钱兑换2](../code500/M518_零钱兑换2.java) 13 | - [M494_目标和](../code400/M494_目标和.java) 14 | 15 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/SwordOffer/old/b03_二维数组中的二分查找.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.SwordOffer.old; 2 | 3 | /** 4 | * 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。 5 | * 请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。 6 | * 7 | * 【思路】 8 | * 从二维数组的右上角往左下角开始比较。 9 | * Created by nibnait on 2016/9/20. 10 | */ 11 | public class b03_二维数组中的二分查找 { 12 | 13 | public static void main(String[] args) { 14 | int[][] matrix = new int[][]{ 15 | {1, 2, 8, 9}, 16 | {2, 4, 9, 12}, 17 | {4, 7, 10, 13}, 18 | {6, 8, 11, 15} 19 | }; 20 | System.out.println(findInPartiallySortedMatrix(matrix, 6)); 21 | } 22 | 23 | private static int findInPartiallySortedMatrix(int[][] matrix, int key) { 24 | int rows = matrix.length; 25 | int cols = matrix[0].length; 26 | if (matrix==null || rows<1 || cols<1){ 27 | return 0; 28 | } 29 | int row = 0; 30 | int col = cols-1; 31 | while (row=0){ 32 | if (matrix[row][col] == key){ 33 | return 1; 34 | } else if (matrix[row][col] < key){ 35 | row++; 36 | } else { 37 | col--; 38 | } 39 | } 40 | return 0; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/SwordOffer/old/b09_斐波那契数列.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.SwordOffer.old; 2 | 3 | /** 4 | * Created by nibnait on 2016/9/20. 5 | */ 6 | public class b09_斐波那契数列 { 7 | 8 | public static void main(String[] args) { 9 | System.out.println(Fib1(10)); 10 | System.out.println(Fibonacci(10)); 11 | } 12 | 13 | private static long Fibonacci(int n) { 14 | 15 | if (n <= 0){ 16 | return 0; 17 | } else if (n == 1){ 18 | return 1; 19 | } else { 20 | long fibNMinusOne = 0; 21 | long fibNMinusTwo = 1; 22 | long fibN = 0; 23 | for (int i = 2; i <= n; i++) { 24 | fibN = fibNMinusOne + fibNMinusTwo; 25 | fibNMinusOne = fibNMinusTwo; 26 | fibNMinusTwo = fibN; 27 | } 28 | return fibN; 29 | } 30 | } 31 | 32 | private static long Fib1(int n) { 33 | return n<2? (n<1?0:1) : Fib1(n-1)+Fib1(n-2); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/SwordOffer/old/e31_连续子数组的最大和.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.SwordOffer.old; 2 | 3 | /** 4 | * 题目:输入一个整型数组,数组里有正数也有负数。数组中一个或连续的多个整数组成一个子数组。求所有子数组的和的最大值。 5 | * 要求时间复杂度为 O(n)。 6 | * 7 | * /src/Algorithm.nowcoder/b_2nd_Season/bb160727/README.md: 8 | * 左神做法: 9 | cur 依次累加各个元素,一旦cur为负数时,则将cur清为零。 10 | 并尝试更新一次result(最大值) 11 | 最终返回result即为子数组的最大累加和 12 | 13 | 解释: 14 | 因为最大和的子数组:其任意数量的前缀一定不为负。 15 | 也就是 cur如果没有累加出到负数,就继续往下走。 即模拟了“前缀不可能为负数”的情况。 16 | 17 | * 18 | * 19 | * Created by nibnait on 2016/10/1. 20 | */ 21 | public class e31_连续子数组的最大和 { 22 | 23 | public static void main(String[] args) { 24 | int[] data = {1, -2, 3, 10, -4, 7, 2, -5}; 25 | int[] data2 = {-2, -8, -1, -5, -9}; 26 | int[] data3 = {2, 8, 1, 5, 9}; 27 | System.out.println(findGreatestSumOfSubArray(data)); 28 | System.out.println(findGreatestSumOfSubArray(data2)); 29 | System.out.println(findGreatestSumOfSubArray(data3)); 30 | } 31 | 32 | private static int findGreatestSumOfSubArray(int[] arr) { 33 | if (arr==null || arr.length<=0){ 34 | return 0; 35 | } 36 | 37 | int cur = arr[0]; 38 | int res = cur; 39 | for (int i = 1; i < arr.length; i++) { 40 | cur += arr[i]; 41 | res = Math.max(res, cur); 42 | cur = cur>0? cur:0; 43 | } 44 | return res; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/SwordOffer/old/f39_1$二叉树的深度.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.SwordOffer.old; 2 | 3 | import cc.tianbin.common.datastruct.BinaryTreeNode; 4 | 5 | /** 6 | * 题目一:输入一棵二叉树的根结点,求该树的深度。 7 | * 从根结点到叶子点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。 8 | * 9 | * 【解】:递归 10 | * 11 | * 12 | * Created by nibnait on 2016/10/1. 13 | */ 14 | public class f39_1$二叉树的深度 { 15 | 16 | public static int TreeDepth(BinaryTreeNode head){ 17 | if (head==null){ 18 | return 0; 19 | } 20 | int left = TreeDepth(head.left); 21 | int right = TreeDepth(head.right); 22 | return left>right? left+1: right+1; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/SwordOffer/old/f46_求1到n的和.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.SwordOffer.old; 2 | 3 | /** 4 | * 题目:求1 + 2 + ···+ n, 5 | * 要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A ? B : C) 6 | * 7 | * 8 | * 这是一道C++序员的题目,书上居然给了4种方法: 9 | * Ⅰ. 利用构造函数求解 10 | * Ⅱ. 利用虚函数求解 11 | * Ⅲ. 利用函数指针求解 12 | * Ⅳ. 利用模板类型求解 13 | * 14 | * 15 | * 对于C艹只会cout和cin的我来说,只看懂了第一个:利用构造函数求解: 16 | * 然而Java中,当你new一个n那么大的Temp型数组,JVM并不会为你执行n次Temp的构造函数。 失败! 17 | * 18 | * Created by nibnait on 2016/10/2. 19 | */ 20 | public class f46_求1到n的和 { 21 | 22 | private static int cnt = 0; 23 | private static int sum = 0; 24 | 25 | static class Temp{ 26 | public Temp() { 27 | cnt++; 28 | sum += cnt; 29 | } 30 | public static int getSum(){ 31 | return sum; 32 | } 33 | } 34 | 35 | public static void main(String[] args) { 36 | int n = 4; 37 | Temp[] temps = new Temp[n]; 38 | System.out.println(Temp.getSum()); //失败。。 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/SwordOffer/old/f47_不用加减乘除做加法.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.SwordOffer.old; 2 | 3 | /** 4 | * 题目:写一个函数,求两个整数之和,要求在函数体内不得使用+、-、×、÷四则运算符号。 5 | * 6 | * 【解】: 7 | * 不用加减乘除,那就只剩下位运算了 8 | * 回到了计算机中是如何做加法的: 9 | * 求 A + B 10 | * while(B != 0){ 11 | * 1. sum = A ^ B; 12 | * 2. carry = (A & B) << 1; //只有A和B都是1时,才有进位 13 | * //如果又进位,则sum与carry还要再异或一次。 14 | * 3. A = sum, B = carry 15 | * } 16 | * 17 | * Created by nibnait on 2016/10/2. 18 | */ 19 | public class f47_不用加减乘除做加法 { 20 | 21 | public static void main(String[] args) { 22 | System.out.println(add(1, 2) + ", " + (1 + 2)); 23 | System.out.println(add(13, 34)+ ", " + (13 + 34)); 24 | System.out.println(add(19, 85)+ ", " + (19 + 95)); 25 | System.out.println(add(865, 245)+ ", " + (865 + 245)); 26 | } 27 | 28 | private static int add(int num1, int num2){ 29 | int sum = 0; 30 | int carry = 0; 31 | while (num2 != 0){ 32 | sum = num1 ^ num2; 33 | carry = (num1 & num2) << 1; 34 | num1 = sum; 35 | num2 = carry; 36 | } 37 | return num1; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/SwordOffer/old/f48_不能被继承的类.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.SwordOffer.old; 2 | 3 | /** 4 | * 题目:设计一个不能被继承的类 5 | * Java中,被final修饰的类,不能被继承 6 | * 7 | * 这里顺便复习一下抽象类和接口的区别吧: 8 | * 抽象类:不能被实例化,他只是把一些类的公共方法、属性抽象出来, 9 | * 当子类继承某个抽象类时,必须重写父类的所有抽象方法 10 | * - 类,只能继承1个 11 | * - abstract不能与private、static、final或native并列修饰同一个方法 12 | * 13 | * 接口:也不能被实例化,他只是抽象出某些类的行为。 14 | * 接口中的所有方法都是抽象的,不能包含实现的方法,也不能包含静态方法 15 | * 实现接口的非抽象类必须实现接口的所有方法,而抽象类不需要 16 | * - 接口,可以实现多个(注意方法名重复) 17 | * - 接口中的成员变量,会被自动转为 public static final的常量,并且必须被显示初始化 18 | * 19 | * 20 | * 原题是用C++设计。 21 | * 书中给了两种方法: 22 | * Ⅰ. 把构造函数和析构函数都设为私有函数。 23 | * 这时,我们可以通过共有的静态函数 来创建和释放类的实例(单例模式) 24 | * Ⅱ. 利用虚拟继承(没看懂 -.-) 25 | * 26 | * Created by nibnait on 2016/10/2. 27 | */ 28 | public abstract class f48_不能被继承的类 { 29 | } 30 | 31 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/a_Sorting/README.md: -------------------------------------------------------------------------------- 1 | ## 稳定性: 2 | 3 | ### 稳定性的概念: 4 | 假定在待排序的记录序列中,存在多个具有**相同的关键字的记录**,若经过排序,这些记录的**相对次序保持不变**,即在原序列中,ri=rj,且ri在rj之前,而在排序后的序列中,ri仍在rj之前,则称这种排序算法是稳定的;**否则称为不稳定的。** 5 | 6 | ### 稳定性的重要性: 7 | 打个比方 : 一个班级参加了一次考试,成绩出来了,总得排个名吧,假如使用的排序方法时不稳定的排序方法,比如就是快速排序方法,按的只是学生的总成绩.等同学们的排名出来后,学生a,b,c的成绩是一样的,但是,各科成绩的顺序却是:c,b,a。。。 不行,再使用这个排序算法重新排了一次,结果却是:a,c,b 了,为什么每次的排名不同嫩 ! 这个就是算法本身的问题了,这个就体现了这个概念---稳定性 8 | 9 | 选择排序、希尔排序、快速排序和堆排序不是稳定的排序算法, 10 | 冒泡排序、插入排序、归并排序、基数排序是稳定的排序算法。 11 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/a_Sorting/a_Bubble.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.a_Sorting; 2 | 3 | import cc.tianbin.common.util.SwapUtil; 4 | 5 | /** 6 | * Bubble_Sort 7 | * 时间复杂度:O(n^2) 8 | * 9 | *【思路】 10 | * 共遍历n次数组A[],(i=[0,n-1]) 11 | * 每次比较 A[j]和A[j+1], 每遍历一次选出一个最大值 放在数组A[]的倒数第i个位置上 12 | * 【 13 | * j的范围可以优化 、 [0,n-1-i] 14 | * 】 15 | * 16 | * Created by nibnait on 2016/9/23. 17 | */ 18 | 19 | public class a_Bubble { 20 | 21 | public static void main(String[] args) { 22 | int[] A = new int[]{54,35,48,36,27,12,44,44,8,14,26,17,28}; 23 | int[] B = new int[13]; 24 | 25 | A = Bubble_Sort(A, 13); 26 | 27 | for (int i = 0; i < A.length; i++) { 28 | System.out.print(A[i]+" "); 29 | } 30 | 31 | } 32 | 33 | public static int[] Bubble_Sort(int[] a, int n) { 34 | 35 | int temp; 36 | for(int i=0; ia[j+1]){ 39 | SwapUtil.swap(a, j, j+1); 40 | } 41 | } 42 | } 43 | return a; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/a_Sorting/a_Selection.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.a_Sorting; 2 | 3 | import cc.tianbin.common.util.SwapUtil; 4 | import cc.tianbin.common.util.SysOut; 5 | import cc.tianbin.common.util.SysRandom; 6 | /** 7 | * Selection_Sort 8 | * 时间复杂度:O(n^2) 9 | * 10 | *【思路】 11 | * 共遍历n次数组A[],(i=[0,n-1]) 12 | * 每次选出一个最小的数 放在数组A[]的第i位上 13 | * 14 | * Created by nibnait on 2016/8/5. 15 | */ 16 | public class a_Selection { 17 | public static void main(String[] args) { 18 | int[] a = SysRandom.generateArr(); 19 | SysOut.printArray(a); 20 | 21 | Selection_Sort(a); 22 | SysOut.printArray(a); 23 | } 24 | 25 | /** 26 | * 不断的选择剩余元素中的最小者 27 | * 比较 N*(N-1)/2次 28 | * 交换 N-1次 29 | * 30 | * 时间复杂度:O(N^2) 31 | */ 32 | public static int[] Selection_Sort(int[] a) { 33 | int N = a.length; 34 | for (int i = 0; i < N - 1; i++) { 35 | int min = i; 36 | for (int j = i + 1; j < N; j++) { 37 | if (a[min] > a[j]) { 38 | min = j; 39 | } 40 | } 41 | SwapUtil.swap(a, i, min); 42 | } 43 | return a; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/a_Sorting/b_Insertion.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.a_Sorting; 2 | 3 | import cc.tianbin.common.util.SwapUtil; 4 | import cc.tianbin.common.util.SysOut; 5 | import cc.tianbin.common.util.SysRandom; 6 | 7 | /** 8 | * Created by nibnait on 2016/8/7. 9 | */ 10 | public class b_Insertion { 11 | public static void main(String[] args) { 12 | int[] a = SysRandom.generateArr(); 13 | SysOut.printArray(a); 14 | 15 | a = Insertion_Sort(a); 16 | SysOut.printArray(a); 17 | } 18 | 19 | /** 20 | * 适用于元素基本(接近)有序的数组, 21 | */ 22 | public static int[] Insertion_Sort(int[] a) { 23 | 24 | int length = a.length; 25 | 26 | for (int i = 1; i < length; i++) { 27 | for (int j = i; j > 0 && a[j] 即a[0]< a[h]< a[2*h]<...,a[1]< a[h+1]< a[2*h+1]<... 22 | //h:1, 4, 13, 41, 121, 364, 1093... 3倍的倍数递增。 23 | public static int[] Shell_Sort(int[] a) { 24 | 25 | int length = a.length; 26 | int h = 1; //步长 27 | while (h < length/3){ 28 | h = 3*h +1; 29 | } 30 | 31 | while (h>0){ 32 | for (int i = h; i < length; i++) {//将数组整理成【h有序数组】, 33 | for (int j = i; j >= h && a[j]= hi) { //lo >= hi 的时候,就说明 不能再分了,可以开始归并了 26 | return; 27 | } 28 | int mid = (lo + hi) / 2; 29 | //递归的将数组分到不能再分 30 | divide(a, lo, mid); 31 | divide(a, mid + 1, hi); 32 | 33 | //开始Merge 34 | Merge(a, lo, mid, hi); 35 | } 36 | 37 | private static void Merge(int[] a, int lo, int mid, int hi) { 38 | //新建一个辅助数组 39 | int aux[] = new int[a.length + 1]; 40 | for (int i = lo; i <= hi; i++) { 41 | aux[i] = a[i]; 42 | } 43 | 44 | //开始合并! 45 | int p1 = lo, p2 = mid + 1; 46 | for (int i = lo; i <= hi; i++) { 47 | if ((aux[p1] <= aux[p2] && p1 <= mid) || p2 > hi) { 48 | a[i] = aux[p1++]; 49 | } else { 50 | a[i] = aux[p2++]; 51 | } 52 | } 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/AlgorithmPrototype/SlidingWindowMaxValue.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.nowcoder.AlgorithmPrototype; 2 | 3 | import cc.tianbin.common.util.SysOut; 4 | 5 | import java.util.LinkedList; 6 | 7 | /** 8 | * 双端队列的操作 9 | *

10 | * Created by nibnait on 2016/9/13. 11 | */ 12 | public class SlidingWindowMaxValue { 13 | 14 | public static void main(String[] args) { 15 | int[] arr = {4, 3, 5, 4, 3, 3, 6, 7}; 16 | int w = 3; 17 | SysOut.printArray(getWindowMaxValue(arr, w)); 18 | } 19 | 20 | private static int[] getWindowMaxValue(int[] arr, int w) { 21 | 22 | if (arr == null || w < 1 || arr.length < w) { 23 | return null; 24 | } 25 | 26 | LinkedList deque = new LinkedList(); 27 | int[] res = new int[arr.length - w + 1]; 28 | int cnt = 0; 29 | for (int i = 0; i < arr.length; i++) { 30 | while (!deque.isEmpty() && arr[deque.peekFirst()] <= arr[i]) { 31 | deque.pollLast(); 32 | } 33 | deque.addLast(i); 34 | if (deque.peekFirst() <= i - w) { 35 | deque.pollFirst(); 36 | } 37 | if (i >= w - 1) { 38 | res[cnt++] = arr[deque.peekFirst()]; 39 | } 40 | } 41 | 42 | return res; 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/AlgorithmPrototype/SubArrayMaxSum.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.nowcoder.AlgorithmPrototype; 2 | 3 | /** 4 | * 子数组最大和(leetcode 53) 5 | * Created by nibnait on 2016/9/10. 6 | */ 7 | public class SubArrayMaxSum { 8 | 9 | public static void main(String[] args) { 10 | int[] arr = new int[]{3,-2,1,-6,4,3,-2,3}; 11 | System.out.println(maxSum(arr)); 12 | } 13 | 14 | /** 15 | * 求子数组最大和 16 | * @param arr 17 | * @return 18 | * 19 | * cur和res 20 | */ 21 | public static int maxSum(int[] arr) { 22 | if (arr==null || arr.length<=0){ 23 | return 0; 24 | } 25 | 26 | int cur = arr[0]; 27 | int res = cur; 28 | for (int i = 1; i < arr.length; i++) { 29 | cur += arr[i]; 30 | res = Math.max(res, cur); 31 | cur = cur>0? cur:0; 32 | } 33 | return res; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/a_1st_Season/aa_Manacher_bfprt_KMP/README.md: -------------------------------------------------------------------------------- 1 | ## Manacher算法: 最长回文字串 2 | 3 | 每个元素之间插入一个字符'#',抵消奇回文与偶回文的差别(任意字符都行,不会影响最终的计算结果) 4 | - pArr[i]:i位置上,所能扩到的最大回文半径 5 | - maxRight:记录回文半径扫到最右位置的下一个位置。(即将到达的位置) 6 | - index:当pR更新的时候,此时回文中心的位置 7 | 8 | 详解:[./Manacher算法.md](Manacher算法.md) 9 | 10 | 11 | ## KMP算法 12 | 【题目】 13 | 给定字符串str1 和str2,请返回str2 在str1 中第一次出现的位置;如果str1 不包含str2,返 14 | 回-1 15 | 【要求】 16 | 时间复杂度O(N) (N为str1的长度) 17 | 18 | 【推广题目】 19 | 给定两棵二叉树的头结点head1 和head2,判断head2 是不是head1 的子树 20 | 【要求】 21 | 时间复杂度O(N) 22 | 23 | - 前缀:从第一个字符开始向后扩,不包含最后一个字符 24 | - 后缀:从最后一个字符向前扩, 不包含第一个字符 25 | 例: S(c) : 在不包含"c"这个字符,只考察"c"前面的字符串,前缀和后缀相同的字符的最大长度。 26 | ababc --> S(c)=2; 27 | aaaac --> S(c)=3; 28 | 29 | - nextArr: 30 | nextArr[0] = -1; 31 | nextArr[1] = 0; 32 | nextArr[i] 33 | 将每一个位置的S(i)右移一位,然后S(0)=-1。 34 | 35 | 36 | 37 | 详解:[./KMP算法.md](./KMP算法.md) 38 | 39 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/b_2nd_Season/bb160727/a_SubArrayMaxSum.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.nowcoder.b_2nd_Season.bb160727; 2 | 3 | /** 4 | * 子数组最大和(leetcode 53) 5 | * Created by nibnait on 2016/9/10. 6 | */ 7 | public class a_SubArrayMaxSum { 8 | 9 | public static void main(String[] args) { 10 | int[] arr = new int[]{3,-2,1,-6,4,3,-2,3}; 11 | System.out.println(maxSum(arr)); 12 | } 13 | 14 | /** 15 | * 求子数组最大和 16 | * @param arr 17 | * @return 18 | * 19 | * cur和res 20 | */ 21 | public static int maxSum(int[] arr) { 22 | if (arr==null || arr.length<0){ 23 | return 0; 24 | } 25 | 26 | int cur = arr[0]; 27 | int res = cur; 28 | for (int i = 1; i < arr.length; i++) { 29 | cur += arr[i]; 30 | res = Math.max(res, cur); 31 | cur = cur>0? cur:0; 32 | } 33 | return res; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/b_2nd_Season/bb160727/b_TwoSubArrayMaxSum.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.nowcoder.b_2nd_Season.bb160727; 2 | 3 | /** 4 | * 求两个子数组最大的累加和 5 | * 6 | * Created by nibnait on 2016/9/10. 7 | */ 8 | public class b_TwoSubArrayMaxSum { 9 | 10 | public static void main(String[] args) { 11 | int[] arr = new int[]{3,-2,1,-6,4,3,-2,3}; 12 | System.out.println(maxSum(arr)); 13 | } 14 | 15 | public static int maxSum(int[] arr) { 16 | 17 | int length = arr.length; 18 | int[] Rmax = new int[length]; 19 | int cur = arr[length-1]; 20 | Rmax[length-1] = cur; 21 | for (int i=length-2; i>=0; i--){ 22 | cur = cur>0? cur: 0; 23 | cur += arr[i]; 24 | Rmax[i] = Math.max(Rmax[i], cur); 25 | }// Rmax遍历完毕 26 | 27 | cur = arr[0]; 28 | int Lmax = arr[0]; 29 | int res = Lmax + Rmax[1]; 30 | for (int i=1; i0? cur: 0; 32 | cur += arr[i]; 33 | Lmax = Math.max(cur, Lmax); 34 | res = Math.max(res, Lmax+Rmax[i+1]); 35 | } 36 | return res; 37 | } 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/b_2nd_Season/bc160803/src/CompleteTreeNodeNumber.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.nowcoder.b_2nd_Season.bc160803.src; 2 | 3 | public class CompleteTreeNodeNumber { 4 | 5 | public static class Node { 6 | public int value; 7 | public Node left; 8 | public Node right; 9 | 10 | public Node(int data) { 11 | this.value = data; 12 | } 13 | } 14 | 15 | public static int nodeNum(Node head) { 16 | if (head == null) { 17 | return 0; 18 | } 19 | return bs(head, 1, mostLeftLevel(head, 1)); 20 | } 21 | 22 | public static int bs(Node node, int l, int h) { 23 | if (l == h) { 24 | return 1; 25 | } 26 | if (mostLeftLevel(node.right, l + 1) == h) { 27 | return (1 << (h - l)) + bs(node.right, l + 1, h); 28 | } else { 29 | return (1 << (h - l - 1)) + bs(node.left, l + 1, h); 30 | } 31 | } 32 | 33 | public static int mostLeftLevel(Node node, int level) { 34 | while (node != null) { 35 | level++; 36 | node = node.left; //一路向左 37 | } 38 | return level - 1; //返回高度 39 | } 40 | 41 | public static void main(String[] args) { 42 | Node head = new Node(1); 43 | head.left = new Node(2); 44 | head.right = new Node(3); 45 | head.left.left = new Node(4); 46 | head.left.right = new Node(5); 47 | head.right.left = new Node(6); 48 | System.out.println(nodeNum(head)); 49 | 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/b_2nd_Season/bc160803/src/MaxSubMatrixSumLessK.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.nowcoder.b_2nd_Season.bc160803.src; 2 | 3 | import cc.tianbin.common.datastruct.BinarySearch; 4 | 5 | public class MaxSubMatrixSumLessK { 6 | 7 | public static int maxSubMatrixSumLessThanK(int[][] m, int sum) { 8 | if (m == null || m.length == 0 || m[0] == null || m[0].length == 0) { 9 | return 0; 10 | } 11 | int res = 0; 12 | for (int i = 0; i < m.length; i++) { 13 | int[] sumArr = new int[m[0].length]; 14 | for (int j = i; j < m.length; j++) { 15 | for (int k = 0; k < m[0].length; k++) { 16 | sumArr[k] += m[j][k]; 17 | } 18 | res = Math.max(res, (j - i + 1) * maxLength(sumArr, sum)); 19 | } 20 | } 21 | return res; 22 | } 23 | 24 | public static int maxLength(int[] arr, int k) { 25 | int[] h = new int[arr.length + 1]; 26 | int sum = 0; 27 | h[0] = sum; 28 | for (int i = 0; i != arr.length; i++) { 29 | sum += arr[i]; 30 | h[i + 1] = Math.max(sum, h[i]); 31 | } 32 | sum = 0; 33 | int res = 0; 34 | int pre = 0; 35 | int len = 0; 36 | for (int i = 0; i != arr.length; i++) { 37 | sum += arr[i]; 38 | pre = BinarySearch.search(h, sum - k); 39 | len = pre == -1 ? 0 : i - pre + 1; 40 | res = Math.max(res, len); 41 | } 42 | return res; 43 | } 44 | 45 | public static void main(String[] args) { 46 | int[][] matrix = { { 1, 0, 1 }, { 0, -2, 3 } }; 47 | System.out.println(maxSubMatrixSumLessThanK(matrix, 2)); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/b_2nd_Season/bc160803/src/PrefixCheck.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.nowcoder.b_2nd_Season.bc160803.src; 2 | 3 | import java.util.HashMap; 4 | 5 | public class PrefixCheck { 6 | 7 | public static class Tries { 8 | private HashMap children = new HashMap();; //字符不挂在结点上,挂在边上! 9 | private boolean end = false; 10 | 11 | public boolean addAndCheck(char[] chs, int i) { 12 | if (end) { 13 | return true; 14 | } 15 | if (i == chs.length) { 16 | end = true; 17 | return !children.isEmpty(); 18 | } 19 | if (!children.containsKey(chs[i])) { 20 | children.put(chs[i], new Tries()); 21 | 22 | } 23 | return children.get(chs[i]).addAndCheck(chs, i + 1); 24 | } 25 | 26 | } 27 | 28 | public static boolean hasPrefix(String[] strs) { 29 | Tries tries = new Tries(); 30 | for (String str : strs) { 31 | if (str == null || str.equals("")) { 32 | return true; 33 | } 34 | if (tries.addAndCheck(str.toCharArray(), 0)) { 35 | return true; 36 | } 37 | } 38 | return false; 39 | } 40 | 41 | public static void main(String[] args) { 42 | String[] strs = { "abcd", "abc" }; 43 | System.out.println(hasPrefix(strs)); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/b_2nd_Season/bc160803/src/SubArrayMaxSum.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.nowcoder.b_2nd_Season.bc160803.src; 2 | 3 | public class SubArrayMaxSum { 4 | 5 | public static int maxSum(int[] arr) { 6 | if (arr == null || arr.length == 0) { 7 | return 0; 8 | } 9 | int max = Integer.MIN_VALUE; 10 | int cur = 0; 11 | for (int i = 0; i != arr.length; i++) { 12 | cur += arr[i]; 13 | max = Math.max(max, cur); 14 | cur = cur < 0 ? 0 : cur; 15 | } 16 | return max; 17 | } 18 | 19 | public static void printArray(int[] arr) { 20 | for (int i = 0; i != arr.length; i++) { 21 | System.out.print(arr[i] + " "); 22 | } 23 | System.out.println(); 24 | } 25 | 26 | public static void main(String[] args) { 27 | int[] arr1 = { -2, -3, -5, 40, -10, -10, 100, 1 }; 28 | System.out.println(maxSum(arr1)); 29 | 30 | int[] arr2 = { -2, -3, -5, 0, 1, 2, -1 }; 31 | System.out.println(maxSum(arr2)); 32 | 33 | int[] arr3 = { -2, -3, -5, -1 }; 34 | System.out.println(maxSum(arr3)); 35 | 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/b_2nd_Season/bc160803/src/SubMatrixMaxSum.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.nowcoder.b_2nd_Season.bc160803.src; 2 | 3 | public class SubMatrixMaxSum { 4 | 5 | public static int maxSum(int[][] m) { 6 | if (m == null || m.length == 0 || m[0].length == 0) { 7 | return 0; 8 | } 9 | int max = Integer.MIN_VALUE; 10 | int cur = 0; 11 | int[] s = null; 12 | for (int i = 0; i != m.length; i++) { 13 | s = new int[m[0].length]; 14 | for (int j = i; j != m.length; j++) { 15 | cur = 0; 16 | for (int k = 0; k != s.length; k++) { 17 | s[k] += m[j][k]; 18 | cur += s[k]; 19 | max = Math.max(max, cur); 20 | cur = cur < 0 ? 0 : cur; 21 | } 22 | } 23 | } 24 | return max; 25 | } 26 | 27 | public static void main(String[] args) { 28 | int[][] matrix = { { -90, 48, 78 }, { 64, -40, 64 }, { -81, -7, 66 } }; 29 | System.out.println(maxSum(matrix)); 30 | 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/b_2nd_Season/bd160810/SlidingWindowMaxValue.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.nowcoder.b_2nd_Season.bd160810; 2 | 3 | import cc.tianbin.common.util.SysOut; 4 | 5 | import java.util.LinkedList; 6 | 7 | /** 8 | * 双端队列的操作 9 | *

10 | * Created by nibnait on 2016/9/13. 11 | */ 12 | public class SlidingWindowMaxValue { 13 | 14 | public static void main(String[] args) { 15 | int[] arr = {4, 3, 5, 4, 3, 3, 6, 7}; 16 | int w = 3; 17 | SysOut.printArray(getWindowMaxValue(arr, w)); 18 | } 19 | 20 | private static int[] getWindowMaxValue(int[] arr, int w) { 21 | 22 | if (arr == null || w < 1 || arr.length < w) { 23 | return null; 24 | } 25 | 26 | LinkedList deque = new LinkedList(); 27 | int[] res = new int[arr.length - w + 1]; 28 | int cnt = 0; 29 | for (int i = 0; i < arr.length; i++) { 30 | while (!deque.isEmpty() && arr[deque.peekFirst()] <= arr[i]) { 31 | deque.pollLast(); 32 | } 33 | deque.addLast(i); 34 | if (deque.peekFirst() <= i - w) { 35 | deque.pollFirst(); 36 | } 37 | if (i >= w - 1) { 38 | res[cnt++] = arr[deque.peekFirst()]; 39 | } 40 | } 41 | 42 | return res; 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/b_2nd_Season/bd160810/src/ReverseStackUsingRecursive.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.nowcoder.b_2nd_Season.bd160810.src; 2 | 3 | import java.util.Stack; 4 | 5 | public class ReverseStackUsingRecursive { 6 | 7 | public static void reverse(Stack stack) { 8 | if (stack.isEmpty()) { 9 | return; 10 | } 11 | int i = getAndRemoveLast(stack); 12 | reverse(stack); 13 | stack.push(i); 14 | } 15 | 16 | public static int getAndRemoveLast(Stack stack) { 17 | int result = stack.pop(); 18 | if (stack.isEmpty()) { 19 | return result; 20 | } else { 21 | int last = getAndRemoveLast(stack); 22 | stack.push(result); 23 | return last; 24 | } 25 | } 26 | 27 | public static void main(String[] args) { 28 | Stack test = new Stack(); 29 | test.push(1); 30 | test.push(2); 31 | test.push(3); 32 | test.push(4); 33 | test.push(5); 34 | reverse(test); 35 | while (!test.isEmpty()) { 36 | System.out.println(test.pop()); 37 | } 38 | 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/b_2nd_Season/bd160810/src/SlidingWindowMaxArray.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.nowcoder.b_2nd_Season.bd160810.src; 2 | 3 | import java.util.LinkedList; 4 | 5 | public class SlidingWindowMaxArray { 6 | 7 | public static int[] getMaxWindow(int[] arr, int w) { 8 | if (arr == null || w < 1 || arr.length < w) { 9 | return null; 10 | } 11 | LinkedList qmax = new LinkedList(); 12 | int[] res = new int[arr.length - w + 1]; 13 | int index = 0; 14 | for (int i = 0; i < arr.length; i++) { 15 | while (!qmax.isEmpty() && arr[qmax.peekLast()] <= arr[i]) { 16 | qmax.pollLast(); 17 | } 18 | qmax.addLast(i); 19 | if (qmax.peekFirst() == i - w) { 20 | qmax.pollFirst(); 21 | } 22 | if (i >= w - 1) { 23 | res[index++] = arr[qmax.peekFirst()]; 24 | } 25 | } 26 | return res; 27 | } 28 | 29 | // for test 30 | public static void printArray(int[] arr) { 31 | for (int i = 0; i != arr.length; i++) { 32 | System.out.print(arr[i] + " "); 33 | } 34 | System.out.println(); 35 | } 36 | 37 | public static void main(String[] args) { 38 | int[] arr = { 4, 3, 5, 4, 3, 3, 6, 7 }; 39 | int w = 3; 40 | printArray(getMaxWindow(arr, w)); 41 | 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/b_2nd_Season/bg160831/src/KMPAlgorithm.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.nowcoder.b_2nd_Season.bg160831.src; 2 | 3 | public class KMPAlgorithm { 4 | 5 | public static int getIndexOf(String s, String m) { 6 | if (s == null || m == null || m.length() < 1 || s.length() < m.length()) { 7 | return -1; 8 | } 9 | char[] ss = s.toCharArray(); 10 | char[] ms = m.toCharArray(); 11 | int si = 0; 12 | int mi = 0; 13 | int[] next = getNextArray(ms); 14 | while (si < ss.length && mi < ms.length) { 15 | if (ss[si] == ms[mi]) { 16 | si++; 17 | mi++; 18 | } else if (next[mi] == -1) { 19 | si++; 20 | } else { 21 | mi = next[mi]; 22 | } 23 | } 24 | return mi == ms.length ? si - mi : -1; 25 | } 26 | 27 | public static int[] getNextArray(char[] ms) { 28 | if (ms.length == 1) { 29 | return new int[] { -1 }; 30 | } 31 | int[] next = new int[ms.length]; 32 | next[0] = -1; 33 | next[1] = 0; 34 | int pos = 2; //当前位置 35 | int cn = 0; //最长匹配前缀字串后面的那个字符位置 36 | while (pos < next.length) { 37 | if (ms[pos - 1] == ms[cn]) { 38 | next[pos++] = ++cn; 39 | } else if (cn > 0) { 40 | cn = next[cn]; 41 | } else { 42 | next[pos++] = 0; 43 | } 44 | } 45 | return next; 46 | } 47 | 48 | public static void main(String[] args) { 49 | String str = "abcabcababaccc"; 50 | String match = "ababa"; 51 | System.out.println(getIndexOf(str, match)); 52 | 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/b_2nd_Season/bj160928/IsBalancedBinaryTree.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.nowcoder.b_2nd_Season.bj160928; 2 | 3 | 4 | import cc.tianbin.common.datastruct.BinaryTreeNode; 5 | 6 | /** 7 | * 判断一棵二叉树是否为 平衡二叉树 8 | * Created by nibnait on 2016/10/9. 9 | */ 10 | public class IsBalancedBinaryTree { 11 | 12 | public static boolean isBalance(BinaryTreeNode head) { 13 | return getHeight(head, 0) != -1; 14 | } 15 | 16 | public static int getHeight(BinaryTreeNode head, int level) { 17 | if (head == null) { 18 | return level; 19 | } 20 | int lh = getHeight(head.left, level + 1); 21 | int rh = getHeight(head.right, level + 1); 22 | if (lh == -1 || rh == -1 || Math.abs(lh - rh) > 1) { 23 | return -1; 24 | } 25 | return Math.max(lh, rh); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/b_2nd_Season/bj160928/IsCompleteBinaryTree.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.nowcoder.b_2nd_Season.bj160928; 2 | 3 | import cc.tianbin.common.datastruct.BinaryTreeNode; 4 | 5 | import java.util.LinkedList; 6 | import java.util.Queue; 7 | 8 | /** 9 | * 判断一棵二叉树是否为 完全二叉树 10 | * Created by nibnait on 2016/10/9. 11 | */ 12 | public class IsCompleteBinaryTree { 13 | 14 | public static boolean isCBT(BinaryTreeNode head) { 15 | if (head == null) { 16 | return true; 17 | } 18 | Queue queue = new LinkedList(); //按层遍历 19 | boolean leaf = false; 20 | BinaryTreeNode l = null; 21 | BinaryTreeNode r = null; 22 | queue.offer(head); 23 | while (!queue.isEmpty()) { 24 | head = queue.poll(); 25 | l = head.left; 26 | r = head.right; 27 | if ( (leaf && (l != null || r != null)) || (l == null && r != null) ) { 28 | //当前是叶结点的阶段 && head居然还有孩子 //不管哪个阶段,此结点只要有右无左 29 | return false; 30 | } 31 | if (l != null) { 32 | queue.offer(l); 33 | } 34 | if (r != null) { 35 | queue.offer(r); 36 | } else { //有左无右 或 无左无右 37 | leaf = true; 38 | } 39 | } 40 | return true; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/b_2nd_Season/bj160928/IsSearchBinaryTree.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.nowcoder.b_2nd_Season.bj160928; 2 | 3 | import cc.tianbin.common.datastruct.BinaryTreeNode; 4 | 5 | /** 6 | * 判断一棵二叉树是否为搜索二叉树 7 | * 8 | * Created by nibnait on 2016/10/9. 9 | */ 10 | public class IsSearchBinaryTree { 11 | 12 | public static boolean isBST(BinaryTreeNode head) { 13 | if (head == null) { 14 | return true; 15 | } 16 | boolean res = true; 17 | BinaryTreeNode pre = null; 18 | BinaryTreeNode cur1 = head; 19 | BinaryTreeNode cur2 = null; 20 | while (cur1 != null) { 21 | cur2 = cur1.left; 22 | if (cur2 != null) { 23 | while (cur2.right != null && cur2.right != cur1) { 24 | cur2 = cur2.right; 25 | } 26 | if (cur2.right == null) { 27 | cur2.right = cur1; 28 | cur1 = cur1.left; 29 | continue; 30 | } else { 31 | cur2.right = null; 32 | } 33 | } 34 | if (pre != null && pre.value > cur1.value) { 35 | res = false; 36 | } 37 | pre = cur1; 38 | cur1 = cur1.right; 39 | } 40 | return res; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/b_2nd_Season/bj160928/RecoverBST.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.nowcoder.b_2nd_Season.bj160928; 2 | 3 | import cc.tianbin.common.datastruct.BinaryTreeNode; 4 | 5 | /** 6 | * 先挖个坑,争取一周之内填上 7 | * 8 | * Created by nibnait on 2016/10/9. 9 | */ 10 | public class RecoverBST { 11 | 12 | public static BinaryTreeNode recoverTree(BinaryTreeNode head) { 13 | 14 | 15 | return head; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/b_2nd_Season/bj160928/src/Problem_13_IsBalancedTree.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithm_practice.nowcoder.b_2nd_Season.bj160928.src; 2 | 3 | public class Problem_13_IsBalancedTree { 4 | 5 | public static class Node { 6 | public int value; 7 | public Node left; 8 | public Node right; 9 | 10 | public Node(int data) { 11 | this.value = data; 12 | } 13 | } 14 | 15 | public static boolean isBalance(Node head) { 16 | return getHeight(head, 0) != -1; 17 | } 18 | 19 | public static int getHeight(Node head, int level) { 20 | if (head == null) { 21 | return level; 22 | } 23 | int lh = getHeight(head.left, level + 1); 24 | int rh = getHeight(head.right, level + 1); 25 | if (lh == -1 || rh == -1 || Math.abs(lh - rh) > 1) { 26 | return -1; 27 | } 28 | return Math.max(lh, rh); 29 | } 30 | 31 | public static void main(String[] args) { 32 | Node head = new Node(1); 33 | head.left = new Node(2); 34 | head.right = new Node(3); 35 | head.left.left = new Node(4); 36 | head.left.right = new Node(5); 37 | head.right.left = new Node(6); 38 | head.right.right = new Node(7); 39 | 40 | System.out.println(isBalance(head)); 41 | 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/KMP-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nibnait/algorithms/4d88870d479793b7bcf8418402251acb9498eec9/src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/KMP-1.png -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/Manacher算法-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nibnait/algorithms/4d88870d479793b7bcf8418402251acb9498eec9/src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/Manacher算法-1.png -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/Manacher算法-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nibnait/algorithms/4d88870d479793b7bcf8418402251acb9498eec9/src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/Manacher算法-2.png -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbb16072701.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nibnait/algorithms/4d88870d479793b7bcf8418402251acb9498eec9/src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbb16072701.png -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbb16072702.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nibnait/algorithms/4d88870d479793b7bcf8418402251acb9498eec9/src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbb16072702.png -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbc16080301.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nibnait/algorithms/4d88870d479793b7bcf8418402251acb9498eec9/src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbc16080301.png -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbc16080302.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nibnait/algorithms/4d88870d479793b7bcf8418402251acb9498eec9/src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbc16080302.png -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbc16080303.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nibnait/algorithms/4d88870d479793b7bcf8418402251acb9498eec9/src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbc16080303.png -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbd16081001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nibnait/algorithms/4d88870d479793b7bcf8418402251acb9498eec9/src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbd16081001.png -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbf16082401.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nibnait/algorithms/4d88870d479793b7bcf8418402251acb9498eec9/src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbf16082401.png -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbf16082402.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nibnait/algorithms/4d88870d479793b7bcf8418402251acb9498eec9/src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbf16082402.png -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbi16091401.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nibnait/algorithms/4d88870d479793b7bcf8418402251acb9498eec9/src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbi16091401.png -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbj16092801.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nibnait/algorithms/4d88870d479793b7bcf8418402251acb9498eec9/src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbj16092801.png -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbj16092802.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nibnait/algorithms/4d88870d479793b7bcf8418402251acb9498eec9/src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbj16092802.png -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbk16101201.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nibnait/algorithms/4d88870d479793b7bcf8418402251acb9498eec9/src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbk16101201.png -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbk16101202.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nibnait/algorithms/4d88870d479793b7bcf8418402251acb9498eec9/src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbk16101202.png -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbk16101203.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nibnait/algorithms/4d88870d479793b7bcf8418402251acb9498eec9/src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbk16101203.png -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbk16101204.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nibnait/algorithms/4d88870d479793b7bcf8418402251acb9498eec9/src/main/java/cc/tianbin/algorithm_practice/nowcoder/image/nowcoderbk16101204.png -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/common/CommonConstants.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.common; 2 | 3 | /** 4 | * Created by nibnait on 2022/06/21 5 | */ 6 | public class CommonConstants { 7 | 8 | public static final Integer TEST_CASE_COUNT_10 = 10; 9 | public static final Integer TEST_CASE_COUNT_1000 = 1000; 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/common/datastruct/BinarySearch.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.common.datastruct; 2 | 3 | /** 4 | * Created by nibnait on 2016/10/2. 5 | */ 6 | public class BinarySearch { 7 | /** 8 | * 二分查找 9 | * @param arr 10 | * @param num 11 | * @return 12 | */ 13 | public static int search(int[] arr, int num) { 14 | int lo = 0; 15 | int hi = arr.length - 1; 16 | int mid = 0; 17 | int res = -1; 18 | while (lo <= hi) { 19 | mid = (lo + hi) >> 1; //防止溢出,移位也更高效。 20 | if (arr[mid] >= num) { 21 | res = mid; 22 | hi = mid - 1; 23 | } else { 24 | lo = mid + 1; 25 | } 26 | } 27 | return res; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/common/datastruct/BinaryTreeNode.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.common.datastruct; 2 | 3 | /** 4 | * 《剑指offer》二叉树结点 5 | * Created by nibnait on 2016/9/15. 6 | */ 7 | public class BinaryTreeNode { 8 | public int value; 9 | public BinaryTreeNode left = null; 10 | public BinaryTreeNode right = null; 11 | 12 | public BinaryTreeNode() { 13 | } 14 | 15 | public BinaryTreeNode(int data) { 16 | this.value = data; 17 | } 18 | 19 | @Override 20 | public String toString() { 21 | return value + ""; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/common/datastruct/BinaryTreeNodeWithParent.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.common.datastruct; 2 | 3 | /** 4 | * Created by nibnait on 2016/10/3. 5 | */ 6 | public class BinaryTreeNodeWithParent { 7 | public int value; 8 | public BinaryTreeNodeWithParent left; 9 | public BinaryTreeNodeWithParent right; 10 | public BinaryTreeNodeWithParent parent; 11 | 12 | public BinaryTreeNodeWithParent() { 13 | } 14 | 15 | public BinaryTreeNodeWithParent(int data) { 16 | this.value = data; 17 | } 18 | 19 | @Override 20 | public String toString() { 21 | return value + ""; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/common/datastruct/ListNode.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.common.datastruct; 2 | 3 | /** 4 | * LeetCode 链表结点 5 | * Created by nibnait on 2016/9/20. 6 | */ 7 | public class ListNode { 8 | public int val; 9 | public ListNode prev = null; 10 | public ListNode next = null; 11 | 12 | public ListNode() { 13 | } 14 | 15 | public ListNode(int data){ 16 | this.val = data; 17 | } 18 | 19 | public ListNode(int val, ListNode next) { 20 | this.val = val; 21 | this.next = next; 22 | } 23 | 24 | public void printListNode() { 25 | String arrow = next != null ? "->" : ""; 26 | System.out.print(val + arrow); 27 | if (next != null) { 28 | next.printListNode(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/common/datastruct/Node.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.common.datastruct; 2 | 3 | import lombok.NoArgsConstructor; 4 | 5 | /** 6 | * 双向链表的节点 7 | * 单向链表的节点(只要不取 prev 这个属性值就好了) 8 | * Created by nibnait on 2022/07/06 9 | */ 10 | @NoArgsConstructor 11 | public class Node { 12 | 13 | public T value; 14 | public Node prev; 15 | public Node next; 16 | 17 | public Node(T value) { 18 | this.value = value; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/common/datastruct/TreeNode.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.common.datastruct; 2 | 3 | /** 4 | * LeetCode 二叉树结点 5 | */ 6 | public class TreeNode { 7 | public Integer val; 8 | public TreeNode left; 9 | public TreeNode right; 10 | 11 | public TreeNode(Integer val) { 12 | this.val = val; 13 | } 14 | 15 | public TreeNode(String val) { 16 | this.val = Integer.valueOf(val); 17 | } 18 | 19 | public TreeNode(Integer val, TreeNode left, TreeNode right) { 20 | this.val = val; 21 | this.left = left; 22 | this.right = right; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/common/enums/ErrorCode.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.common.enums; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | /** 7 | * Created by nibnait on 2021/09/01 8 | */ 9 | @Getter 10 | @AllArgsConstructor 11 | public enum ErrorCode { 12 | SUCCESS(0L, "success"), 13 | SERVICE_ERROR(83000004L, "service error"), 14 | 15 | ; 16 | 17 | private Long code; 18 | private String message; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/common/model/Person.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.common.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.List; 8 | import java.util.Objects; 9 | 10 | /** 11 | * 实体类 12 | * Created by nibnait on 2020-02-24 13 | */ 14 | @Data 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | public class Person { 18 | 19 | private String name; 20 | private Integer age; 21 | private Byte gender; 22 | private String phone; 23 | private Boolean isBigBoolean; 24 | private boolean isSmallBoolean; 25 | private List children; 26 | 27 | public Person(String name, Integer age) { 28 | this.name = name; 29 | this.age = age; 30 | } 31 | 32 | public static Person buildByAge(int age) { 33 | Person person = new Person(); 34 | person.setAge(age); 35 | return person; 36 | } 37 | 38 | @Override 39 | public boolean equals(Object o) { 40 | if (this == o) return true; 41 | if (o == null || getClass() != o.getClass()) return false; 42 | Person person = (Person) o; 43 | return Objects.equals(name, person.name) && 44 | Objects.equals(age, person.age); 45 | } 46 | 47 | @Override 48 | public int hashCode() { 49 | return Objects.hash(name, age); 50 | } 51 | } -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/common/model/PersonDTO.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.common.model; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * 实体类 7 | * Created by nibnait on 2020-02-24 8 | */ 9 | @Data 10 | public class PersonDTO { 11 | 12 | private String name; 13 | private Integer age; 14 | private Byte gender; 15 | private String phone; 16 | private Boolean isBigBoolean; 17 | private boolean isSmallBoolean; 18 | } -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/common/util/ConvertUtils.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.common.util; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | import java.util.stream.Collectors; 6 | 7 | /** 8 | * Created by nibnait on 2023/03/26 9 | */ 10 | public class ConvertUtils { 11 | 12 | private ConvertUtils() { 13 | } 14 | 15 | public static List convert2IntegerList(int[] arr) { 16 | return Arrays.stream(arr) 17 | .boxed() 18 | .collect(Collectors.toList()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/common/util/CopyUtil.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.common.util; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * Created by nibnait on 2022/11/03 7 | */ 8 | public class CopyUtil { 9 | 10 | public static int[] copy(int[] arr) { 11 | return Arrays.copyOf(arr, arr.length); 12 | } 13 | 14 | public static char[][] copy(char[][] board) { 15 | int row = board.length; 16 | int col = board[0].length; 17 | char[][] ans = new char[row][col]; 18 | for (int i = 0; i < row; i++) { 19 | for (int j = 0; j < col; j++) { 20 | ans[i][j] = board[i][j]; 21 | } 22 | } 23 | return ans; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/common/util/GenerateUUID.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.common.util; 2 | 3 | import junit.framework.TestCase; 4 | import org.junit.Test; 5 | 6 | import java.util.UUID; 7 | 8 | /* 9 | 生成博客的UUID 10 | */ 11 | public class GenerateUUID extends TestCase { 12 | 13 | @Test 14 | public void testCase() { 15 | System.out.println(UUID.randomUUID().toString()); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/common/util/LogUtil.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.common.util; 2 | 3 | import io.github.nibnait.common.utils.DataUtils; 4 | 5 | import java.util.function.Function; 6 | 7 | /** 8 | * Created by nibnait on 2022/12/26 9 | */ 10 | public class LogUtil { 11 | 12 | private LogUtil() { 13 | throw new AssertionError("工具类不允许被实例化"); 14 | } 15 | 16 | public static void printf(String format, Object... args) { 17 | System.out.println(String.format(format, args)); 18 | } 19 | 20 | public static void print(Object obj) { 21 | System.out.print(obj); 22 | } 23 | 24 | public static void println(Object obj, Function function, T t) { 25 | System.out.println(obj); 26 | function.apply(t); 27 | } 28 | 29 | public static void log(String format, Object... args) { 30 | System.out.println(DataUtils.format(format, args)); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/common/util/README.md: -------------------------------------------------------------------------------- 1 | common.util 包 这里不再维护。 2 | 3 | 移步 [https://github.com/nibnait/common-enhance](https://github.com/nibnait/common-enhance) 4 | 5 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/common/util/StandardInit.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.common.util; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * 标准初始化一个结构体 7 | */ 8 | public class StandardInit { 9 | 10 | public static Stack initStack() { 11 | Stack stack = new Stack(); 12 | stack.push(5); 13 | stack.push(4); 14 | stack.push(3); 15 | stack.push(2); 16 | stack.push(1); 17 | return stack; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/common/util/SwapUtil.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.common.util; 2 | 3 | /** 4 | * Created by nibnait on 2016/8/5. 5 | */ 6 | public class SwapUtil { 7 | 8 | public static void swap(String[] a, int i, int j){ 9 | String temp; 10 | temp = a[i]; 11 | a[i] = a[j]; 12 | a[j] = temp; 13 | } 14 | 15 | public static void swap(int[] a, int i, int j){ 16 | 17 | int temp; 18 | temp = a[i]; 19 | a[i] = a[j]; 20 | a[j] = temp; 21 | /* a[i] ^= a[j]; 22 | a[j] ^= a[i]; 23 | a[i] ^= a[j];*/ 24 | } 25 | 26 | public static void swap(char[] a, int i, int j){ 27 | char tmp; 28 | tmp = a[i]; 29 | a[i] = a[j]; 30 | a[j] = tmp; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/common/util/SystemUtil.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.common.util; 2 | 3 | import java.net.InetAddress; 4 | import java.util.concurrent.TimeUnit; 5 | 6 | public class SystemUtil { 7 | private static final String DEFAULT_IP = "127.0.0.1"; 8 | 9 | public static String getLocalIpAddress() { 10 | String ip = DEFAULT_IP; 11 | try { 12 | InetAddress inetAddress = InetAddress.getLocalHost(); 13 | ip = new String(inetAddress.getHostAddress()); 14 | } catch (Exception e) { 15 | e.printStackTrace(); 16 | } 17 | return ip; 18 | } 19 | 20 | public static void sleep(int t, TimeUnit u) { 21 | try { 22 | u.sleep(t); 23 | } catch (InterruptedException e) { 24 | } 25 | } 26 | 27 | public static void printCuttingLine() { 28 | System.out.println("================================================"); 29 | } 30 | 31 | public static void printLiteCuttingLine() { 32 | System.out.println("--------------------------------------------------"); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/common/util/binaryTree/SerializeAndReConstructTree.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.common.util.binaryTree; 2 | 3 | import cc.tianbin.common.datastruct.TreeNode; 4 | 5 | import java.util.Queue; 6 | 7 | /** 8 | * Created by nibnait on 2022/10/27 9 | */ 10 | public interface SerializeAndReConstructTree { 11 | 12 | Queue preSerial(TreeNode head); 13 | 14 | Queue posSerial(TreeNode head); 15 | 16 | Queue levelSerial(TreeNode head); 17 | 18 | TreeNode buildByPreQueue(Queue pre); 19 | 20 | TreeNode buildByPosQueue(Queue pos); 21 | 22 | TreeNode buildByLevelQueue(Queue level); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/data_struct/Node.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.data_struct; 2 | 3 | /** 4 | * Created by nibnait on 2022/11/02 5 | */ 6 | public class Node { 7 | public T value; 8 | 9 | public Node(T v) { 10 | value = v; 11 | } 12 | 13 | public static Node v(T v) { 14 | return new Node(v); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/data_struct/README.md: -------------------------------------------------------------------------------- 1 | # [《算法(第4版)》](https://book.douban.com/subject/19952400/) 2 | 3 | Home Page:[https://algs4.cs.princeton.edu/home/](https://algs4.cs.princeton.edu/home/) 4 | 5 | Source Code:[https://algs4.cs.princeton.edu/code/](https://algs4.cs.princeton.edu/code/) 6 | 7 | 8 | ## 树 9 | ### 平衡二叉树 10 | - [S110_平衡二叉树](../algorithm_practice/LeetCode/E110_平衡二叉树.java) 11 | 12 | ### [BST(二叉查找树)](./ds2_树/二叉查找树) 13 | ### [AVL(平衡二叉查找树)](./ds2_树/平衡查找树) 14 | 15 | ## 图 16 | - [BFS(广度优先遍历)](./ds4_图/BFS.java) 17 | - [DFS(深度优先遍历)](./ds4_图/DFS.java) 18 | - [M547_朋友圈](../algorithm_practice/LeetCode/code500/M547_朋友圈.java) 19 | 20 | ## 堆(堆排序问题) 21 | - [大顶堆](./ds1_堆/MaxHeap.java) 22 | - [小顶堆](./ds1_堆/MinHeap.java) 23 | - [M215_数组中的第K个最大元素](../algorithm_practice/LeetCode/code200/M215_数组中的第K个最大元素.java) -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/data_struct/ds1_堆/MyHeap.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.data_struct.ds1_堆; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Created by nibnait on 2022/10/24 7 | */ 8 | public interface MyHeap { 9 | 10 | boolean isEmpty(); 11 | 12 | boolean isFull(); 13 | 14 | default boolean contains(T obj) { 15 | throw new UnsupportedOperationException("不支持 contains 功能"); 16 | } 17 | 18 | void push(T obj); 19 | 20 | T peek(); 21 | 22 | T pop(); 23 | 24 | default void remove(T obj) { 25 | throw new UnsupportedOperationException("不支持 remove 功能"); 26 | } 27 | 28 | default void resign(T obj) { 29 | throw new UnsupportedOperationException("不支持 resign 功能"); 30 | } 31 | 32 | List getAllElements(); 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/data_struct/ds2_树/二叉查找树/BinarySearchTreeNode.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.data_struct.ds2_树.二叉查找树; 2 | 3 | /** 4 | * 二叉搜索树结点 5 | * Created by nibnait on 2019-07-25 6 | */ 7 | public class BinarySearchTreeNode, Value> { 8 | 9 | /** 10 | * 键(用于排序) 11 | */ 12 | public Key key; 13 | 14 | /** 15 | * 值(用于存储) 16 | */ 17 | public Value value; 18 | 19 | /** 20 | * 左子树 21 | */ 22 | public BinarySearchTreeNode left; 23 | 24 | /** 25 | * 右子树 26 | */ 27 | public BinarySearchTreeNode right; 28 | 29 | /** 30 | * 以该结点为根的子树中的结点总数 31 | */ 32 | public Integer N; 33 | 34 | public BinarySearchTreeNode(Key key, Value value) { 35 | this.key = key; 36 | this.value = value; 37 | this.N = 1; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/data_struct/ds2_树/平衡查找树/AVLNode.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.data_struct.ds2_树.平衡查找树; 2 | 3 | import cc.tianbin.data_struct.ds2_树.二叉查找树.BinarySearchTreeNode; 4 | 5 | /** 6 | * 平衡查找树结点 7 | * Created by nibnait on 2019-07-25 8 | */ 9 | public class AVLNode extends BinarySearchTreeNode { 10 | 11 | /** 12 | * 此时我们将BSTNode中的N 理解为:该结点的高度 13 | * @param key 14 | * @param value 15 | */ 16 | public AVLNode(Comparable key, Object value) { 17 | super(key, value); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/data_struct/ds2_树/平衡查找树/AVLTree.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.data_struct.ds2_树.平衡查找树; 2 | 3 | /** 4 | * 平衡查找树 5 | * Created by nibnait on 2019-07-25 6 | */ 7 | public abstract class AVLTree, Value> { 8 | 9 | /***************************** 基本方法 *******************/ 10 | /** 11 | * 插入 12 | * @param key 13 | * @param value 14 | * @return 15 | */ 16 | public abstract AVLNode put(Key key, Value value); 17 | 18 | /** 19 | * 查找 20 | * @param key 21 | * @return 22 | */ 23 | public abstract Value get(Key key); 24 | 25 | /** 26 | * 删除 27 | * @param key 28 | */ 29 | public abstract void delete(Key key); 30 | 31 | /***************************** 其他方法 *******************/ 32 | public abstract void deleteMin(); 33 | public abstract void deleteMax(); 34 | 35 | public abstract AVLNode floor(Key key); 36 | public abstract AVLNode ceiling(Key key); 37 | 38 | public abstract int rank(Key key); 39 | public abstract Key select(Key key); 40 | 41 | public abstract Iterable keys(); 42 | 43 | /***************************** 基本操作 *******************/ 44 | /** 45 | * 左旋 46 | * @param h 47 | * @return 48 | */ 49 | private AVLNode rotateLeft(AVLNode h) { 50 | 51 | return null; 52 | } 53 | 54 | /** 55 | * 右旋 56 | * @param h 57 | * @return 58 | */ 59 | private AVLNode rotateRight(AVLNode h) { 60 | 61 | return null; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/data_struct/ds2_树/平衡查找树/AVLTreeImpl.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.data_struct.ds2_树.平衡查找树; 2 | 3 | /** 4 | * 平衡查找树实现 5 | * Created by nibnait on 2019-07-25 6 | */ 7 | public class AVLTreeImpl extends AVLTree{ 8 | 9 | /***************************** 基本方法 *******************/ 10 | @Override 11 | public AVLNode put(Comparable comparable, Object o) { 12 | 13 | return null; 14 | } 15 | 16 | @Override 17 | public Object get(Comparable comparable) { 18 | return null; 19 | } 20 | 21 | @Override 22 | public void delete(Comparable comparable) { 23 | 24 | } 25 | 26 | /***************************** 其他方法 *******************/ 27 | @Override 28 | public void deleteMin() { 29 | 30 | } 31 | 32 | @Override 33 | public void deleteMax() { 34 | 35 | } 36 | 37 | @Override 38 | public AVLNode floor(Comparable comparable) { 39 | return null; 40 | } 41 | 42 | @Override 43 | public AVLNode ceiling(Comparable comparable) { 44 | return null; 45 | } 46 | 47 | @Override 48 | public int rank(Comparable comparable) { 49 | return 0; 50 | } 51 | 52 | @Override 53 | public Comparable select(Comparable comparable) { 54 | return null; 55 | } 56 | 57 | @Override 58 | public Iterable keys() { 59 | return null; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/data_struct/ds2_树/平衡查找树/AVLTreeTest.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.data_struct.ds2_树.平衡查找树; 2 | 3 | import junit.framework.TestCase; 4 | import org.junit.Test; 5 | 6 | /** 7 | * 平衡二叉查找树 测试类 8 | * Created by nibnait on 2019-07-31 9 | */ 10 | public class AVLTreeTest extends TestCase { 11 | 12 | @Test 13 | public void testCase() { 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/data_struct/ds2_树/平衡查找树/RedBlackNode.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.data_struct.ds2_树.平衡查找树; 2 | 3 | /** 4 | * 红黑树结点 5 | * Created by nibnait on 2019-07-25 6 | */ 7 | public class RedBlackNode, Value> { 8 | 9 | public static final boolean RED = true; 10 | public static final boolean BLACK = false; 11 | 12 | /** 13 | * 键(用于排序) 14 | */ 15 | public Key key; 16 | 17 | /** 18 | * 值(用于存储) 19 | */ 20 | public Value value; 21 | 22 | /** 23 | * 左子树 24 | */ 25 | public RedBlackNode left; 26 | 27 | /** 28 | * 右子树 29 | */ 30 | public RedBlackNode right; 31 | 32 | /** 33 | * 以该结点为根的子树中的结点总数 34 | */ 35 | public Integer N; 36 | 37 | /** 38 | * 指向该结点的链接的颜色 39 | */ 40 | public boolean color; 41 | 42 | public RedBlackNode(Key key, Value value, boolean color) { 43 | this.key = key; 44 | this.value = value; 45 | this.N = 1; 46 | this.color = color; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/data_struct/ds2_树/平衡查找树/RedBlackTreeTest.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.data_struct.ds2_树.平衡查找树; 2 | 3 | import junit.framework.TestCase; 4 | import org.junit.Test; 5 | 6 | /** 7 | * 红黑树 测试类 8 | * Created by nibnait on 2019-07-31 9 | */ 10 | public class RedBlackTreeTest extends TestCase { 11 | 12 | @Test 13 | public void testCase() { 14 | RedBlackTree redBlackTree = new RedBlackTreeImpl(); 15 | redBlackTree.put('A', 1); 16 | redBlackTree.put('B', 1); 17 | redBlackTree.put('C', 1); 18 | redBlackTree.put('D', 1); 19 | redBlackTree.put('E', 1); 20 | 21 | System.out.println("\nRedBlackTree.size() = " + redBlackTree.size()); 22 | 23 | redBlackTree.delete('B'); 24 | System.out.println("\nRedBlackTree.size() = " + redBlackTree.size()); 25 | 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/data_struct/ds3_并查集/MyUnionFind.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.data_struct.ds3_并查集; 2 | 3 | /** 4 | * Created by nibnait on 2022/11/02 5 | */ 6 | public interface MyUnionFind { 7 | 8 | /** 9 | * 找到 当前节点 的代表节点 10 | */ 11 | T findAncestor(T cur); 12 | 13 | /** 14 | * 是否在同一个集合内 15 | */ 16 | boolean isSameSet(T a, T b); 17 | 18 | /** 19 | * 把 a 节点,并入 b 节点所在集合中 20 | */ 21 | void union(T a, T b); 22 | 23 | /** 24 | * 当前一共有多少个集合 25 | */ 26 | int size(); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/data_struct/ds4_图/Edge.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.data_struct.ds4_图; 2 | 3 | /** 4 | * Created by nibnait on 2022/11/06 5 | */ 6 | public class Edge { 7 | 8 | public int weight; 9 | 10 | public Node from; 11 | 12 | public Node to; 13 | 14 | public Edge(int weight, Node from, Node to) { 15 | this.weight = weight; 16 | this.from = from; 17 | this.to = to; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/data_struct/ds4_图/Graph.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.data_struct.ds4_图; 2 | 3 | import java.util.HashMap; 4 | import java.util.HashSet; 5 | import java.util.Map; 6 | import java.util.Set; 7 | 8 | /** 9 | * Created by nibnait on 2022/11/06 10 | */ 11 | public class Graph { 12 | 13 | public Map nodes; 14 | 15 | public Set edges; 16 | 17 | public Graph() { 18 | nodes = new HashMap<>(); 19 | edges = new HashSet<>(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/data_struct/ds4_图/GraphGenerator.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.data_struct.ds4_图; 2 | 3 | /** 4 | * Created by nibnait on 2022/11/06 5 | */ 6 | public class GraphGenerator { 7 | 8 | 9 | /** 10 | * matrix 为一个 N*3 的矩阵,表示一个图中的所有边 11 | * [weight, from节点上的值, to节点上的值] 12 | *

13 | * [5, 0, 7] 14 | * [3, 0, 1] 15 | */ 16 | public static Graph createGraph(int[][] matrix) { 17 | Graph graph = new Graph(); 18 | for (int i = 0; i < matrix.length; i++) { 19 | // 拿到每一条边, matrix[i] 20 | int weight = matrix[i][0]; 21 | int from = matrix[i][1]; 22 | int to = matrix[i][2]; 23 | if (!graph.nodes.containsKey(from)) { 24 | graph.nodes.put(from, new Node(from)); 25 | } 26 | if (!graph.nodes.containsKey(to)) { 27 | graph.nodes.put(to, new Node(to)); 28 | } 29 | Node fromNode = graph.nodes.get(from); 30 | Node toNode = graph.nodes.get(to); 31 | Edge newEdge = new Edge(weight, fromNode, toNode); 32 | fromNode.nexts.add(toNode); 33 | fromNode.out++; 34 | toNode.in++; 35 | fromNode.edges.add(newEdge); 36 | graph.edges.add(newEdge); 37 | } 38 | 39 | return graph; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/data_struct/ds4_图/Node.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.data_struct.ds4_图; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * 图中的点 8 | * Created by nibnait on 2022/11/06 9 | */ 10 | public class Node { 11 | 12 | // 当前点的 值 13 | public int value; 14 | // 入度 15 | public int in; 16 | // 出度 17 | public int out; 18 | // 从当前点出发的 下一个点 19 | public List nexts; 20 | // 从当前点出发的 边 21 | public List edges; 22 | 23 | public Node(int value) { 24 | this.value = value; 25 | in = 0; 26 | out = 0; 27 | nexts = new ArrayList<>(); 28 | edges = new ArrayList<>(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/hessian/序列化结果对比/Student.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.hessian.序列化结果对比; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * Created by nibnait on 2020/11/12 11 | */ 12 | @Data 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class Student implements Serializable { 16 | private static final long serialVersionUID = 1L; 17 | 18 | private int id; 19 | private String name; 20 | private transient String gender; 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/IO/1.txt: -------------------------------------------------------------------------------- 1 | 123 2 | 456 3 | 789 -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/IO/classpath/ResourcesReaderUtil.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.IO.classpath; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | 6 | /** 7 | * Created by nibnait on 2020/11/12 8 | */ 9 | public class ResourcesReaderUtil { 10 | public InputStream getResource(String fileName) throws IOException { 11 | return this.getClass().getResourceAsStream(fileName); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/IO/classpath/RpcConfig.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.IO.classpath; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * Created by nibnait on 2020/11/12 7 | */ 8 | @Data 9 | public class RpcConfig { 10 | public String protocol; 11 | public String group; 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/proxy/README.md: -------------------------------------------------------------------------------- 1 | # JDK动态代理 2 | 核心:InvocationHandler的invoke()方法 3 | 4 | 使用Proxy.newProxyInstance() 产生代理对象。 5 | 6 | 也可以通过Proxy.getProxyClass(classloader, clazz) 获取动态代理类,然后通过反射机制获取代理类的构造方法,通过构造函数.newInstance()来新建代理对象,并将自定义的InvocationHandler传入,即可返回新的代理对象。 7 | 8 | # CGLIB 9 | 核心:MethodInterceptor 目标拦截器 10 | 11 | 使用Enhancer.create()方法,通过ASM框架,来转换字节码的方式生成一个新的代理类。 12 | 13 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/proxy/cglib/Person.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.proxy.cglib; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * 没有实现接口,需要CGlib动态代理的目标类 7 | * 8 | * @author nibnait 9 | * @version $Id: Person.java, v 0.1 2019-09-02 下午3:37 nibnait Exp $$ 10 | */ 11 | @Data 12 | public class Person { 13 | 14 | private String name; 15 | 16 | public Person() { 17 | this.name = "Jerry"; 18 | } 19 | 20 | public String eat(String food) { 21 | System.out.println(this.name + " eat " + food); 22 | return food; 23 | } 24 | 25 | public int walk(int step) { 26 | System.out.println(this.name + " walked " + step + " step"); 27 | return step; 28 | } 29 | 30 | public int sleep(int count) { 31 | System.out.println(this.name + " sleeped " + count + " hour"); 32 | return count; 33 | } 34 | 35 | final public int play(int count) { 36 | System.out.println(this.name + " played " + count + " hour"); 37 | return count; 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/proxy/cglib/TargetInterceptor.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.proxy.cglib; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import net.sf.cglib.proxy.MethodInterceptor; 5 | import net.sf.cglib.proxy.MethodProxy; 6 | 7 | import java.lang.reflect.Method; 8 | 9 | /** 10 | * 目标对象拦截器,实现MethodInterceptor 11 | * 12 | * @author nibnait 13 | * @version $Id: TargetInterceptor.java, v 0.1 2019-09-02 下午3:45 nibnait Exp $$ 14 | */ 15 | public class TargetInterceptor implements MethodInterceptor { 16 | 17 | /** 18 | * 重写拦截方法,在方法前后加入业务 19 | * 20 | * @param obj 目标对象 21 | * @param method 目标方法 22 | * @param params 参数 23 | * @param proxy CGlib方法代理对象 24 | * @return 25 | * @throws Throwable 26 | */ 27 | @Override 28 | public Object intercept(Object obj, Method method, Object[] params, MethodProxy proxy) throws Throwable { 29 | System.out.println("调用前 params: " + JSON.toJSONString(params)); 30 | Object result = proxy.invokeSuper(obj, params); 31 | System.out.println("调用后 method: " + method.getName() + ", result: " + result); 32 | return result; 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/proxy/cglib/TargetMethodCallbackFilter.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.proxy.cglib; 2 | 3 | import net.sf.cglib.proxy.CallbackFilter; 4 | 5 | import java.lang.reflect.Method; 6 | 7 | /** 8 | * 回调方法过滤 9 | * 10 | * @author nibnait 11 | * @version $Id: TargetMethodCallbackFilter.java, v 0.1 2019-09-02 下午4:21 nibnait Exp $$ 12 | */ 13 | public class TargetMethodCallbackFilter implements CallbackFilter { 14 | 15 | /** 16 | * 过滤方法 17 | * 返回的值为数字,代表了Callback数组中的索引位置,要到用的Callback 18 | */ 19 | @Override 20 | public int accept(Method method) { 21 | if(method.getName().equals("eat")){ 22 | System.out.println("filter eat ==0"); 23 | return 0; 24 | } 25 | 26 | if(method.getName().equals("walk")){ 27 | System.out.println("filter walk ==1"); 28 | return 1; 29 | } 30 | 31 | if(method.getName().equals("sleep")){ 32 | System.out.println("filter sleep ==2"); 33 | return 2; 34 | } 35 | return 0; 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/proxy/cglib/TargetResultFixed.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.proxy.cglib; 2 | 3 | import net.sf.cglib.proxy.FixedValue; 4 | 5 | /** 6 | * 表示锁定方法返回值,无论被代理类的方法返回什么值,回调方法都返回固定值。 7 | * 8 | * @author nibnait 9 | * @version $Id: TargetResultFixed.java, v 0.1 2019-09-02 下午4:26 nibnait Exp $$ 10 | */ 11 | public class TargetResultFixed implements FixedValue { 12 | 13 | /** 14 | * 该类实现FixedValue接口,同时锁定回调值为999 15 | * (整型,CallbackFilter中定义的使用FixedValue型回调的方法为getConcreteMethodFixedValue,该方法返回值为整型)。 16 | */ 17 | @Override 18 | public Object loadObject() throws Exception { 19 | System.out.println("锁定结果"); 20 | Object obj = 999; 21 | return obj; 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/proxy/cglib/lazyloader/ConcreteClassDispatcher.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.proxy.cglib.lazyloader; 2 | 3 | import cc.tianbin.common.model.Person; 4 | import net.sf.cglib.proxy.Dispatcher; 5 | 6 | /** 7 | * @author nibnait 8 | * @version $Id: ConcreteClassDispatcher.java, v 0.1 2019-09-02 下午4:36 nibnait Exp $$ 9 | */ 10 | public class ConcreteClassDispatcher implements Dispatcher { 11 | 12 | @Override 13 | public Object loadObject() throws Exception { 14 | System.out.println("before Dispatcher..."); 15 | PropertyBean propertyBean = new PropertyBean(); 16 | propertyBean.setKey("xxx"); 17 | propertyBean.setValue(new Person()); 18 | System.out.println("after Dispatcher..."); 19 | return propertyBean; 20 | } 21 | 22 | } 23 | 24 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/proxy/cglib/lazyloader/ConcreteClassLazyLoader.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.proxy.cglib.lazyloader; 2 | 3 | import cc.tianbin.common.model.Person; 4 | import net.sf.cglib.proxy.LazyLoader; 5 | 6 | /** 7 | * @author nibnait 8 | * @version $Id: ConcreteClassLazyLoader.java, v 0.1 2019-09-02 下午4:36 nibnait Exp $$ 9 | */ 10 | public class ConcreteClassLazyLoader implements LazyLoader { 11 | /** 12 | * 对需要延迟加载的对象添加代理,在获取该对象属性时先通过代理类回调方法进行对象初始化。 13 | * 在不需要加载该对象时,只要不去获取该对象内属性,该对象就不会被初始化了(在CGLib的实现中只要去访问该对象内属性的getter方法, 14 | * 就会自动触发代理类回调)。 15 | */ 16 | @Override 17 | public Object loadObject() throws Exception { 18 | System.out.println("before lazyLoader..."); 19 | PropertyBean propertyBean = new PropertyBean(); 20 | propertyBean.setKey("zghw"); 21 | propertyBean.setValue(new Person()); 22 | System.out.println("after lazyLoader..."); 23 | return propertyBean; 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/proxy/cglib/lazyloader/PropertyBean.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.proxy.cglib.lazyloader; 2 | 3 | import lombok.Data; 4 | import lombok.ToString; 5 | 6 | /** 7 | * @author nibnait 8 | * @version $Id: PropertyBean.java, v 0.1 2019-09-02 下午4:35 nibnait Exp $$ 9 | */ 10 | @Data 11 | @ToString 12 | public class PropertyBean { 13 | private String key; 14 | private Object value; 15 | 16 | } -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/proxy/jdk/Calculator.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.proxy.jdk; 2 | 3 | /** 4 | * Created by nibnait on 2020/11/23 5 | */ 6 | public interface Calculator { 7 | int add(int x, int y); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/proxy/jdk/CalculatorImpl.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.proxy.jdk; 2 | 3 | /** 4 | * Created by nibnait on 2020/11/23 5 | */ 6 | public class CalculatorImpl implements Calculator { 7 | @Override 8 | public int add(int x, int y) { 9 | return x + y; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/proxy/jdk/HelloService.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.proxy.jdk; 2 | 3 | /** 4 | * @author nibnait 5 | * @version $Id: HelloService.java, v 0.1 2019-09-02 下午7:03 nibnait Exp $$ 6 | */ 7 | public interface HelloService { 8 | void sayHello(); 9 | 10 | void speak(String word); 11 | } -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/proxy/jdk/HelloServiceImpl.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.proxy.jdk; 2 | 3 | /** 4 | * @author nibnait 5 | * @version $Id: HelloServiceImpl.java, v 0.1 2019-09-02 下午7:04 nibnait Exp $$ 6 | */ 7 | public class HelloServiceImpl implements HelloService { 8 | 9 | @Override 10 | public void sayHello() { 11 | System.out.println("Hello world!"); 12 | } 13 | 14 | @Override 15 | public void speak(String word) { 16 | System.out.println("speak" + word); 17 | } 18 | } -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/proxy/jdk/动态代理/DynamicProxy.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.proxy.jdk.动态代理; 2 | 3 | import cc.tianbin.demo.java.proxy.jdk.动态代理.handler.LogHandler; 4 | import org.junit.Test; 5 | import cc.tianbin.demo.java.proxy.jdk.Calculator; 6 | import cc.tianbin.demo.java.proxy.jdk.CalculatorImpl; 7 | 8 | import java.lang.reflect.Proxy; 9 | 10 | /** 11 | * Created by nibnait on 2020/11/23 12 | */ 13 | public class DynamicProxy { 14 | 15 | @Test 16 | public void testCase() { 17 | CalculatorImpl calculator = new CalculatorImpl(); 18 | 19 | Calculator proxy = (Calculator) Proxy.newProxyInstance( 20 | Calculator.class.getClassLoader(), 21 | new Class[]{Calculator.class}, 22 | new LogHandler(new CalculatorImpl()) 23 | ); 24 | 25 | int sum = proxy.add(1, 2); 26 | System.out.println("\nproxy excute res: " + sum); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/proxy/jdk/动态代理/handler/LogHandler.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.proxy.jdk.动态代理.handler; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | 5 | import java.lang.reflect.InvocationHandler; 6 | import java.lang.reflect.Method; 7 | 8 | /** 9 | * Created by nibnait on 2020/11/23 10 | */ 11 | public class LogHandler implements InvocationHandler { 12 | 13 | /** 14 | * 代理的对象 15 | */ 16 | private Object target; 17 | 18 | public LogHandler(Object target) { 19 | this.target = target; 20 | } 21 | 22 | @Override 23 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 24 | this.doBefore(); 25 | 26 | Object res = method.invoke(target, args); 27 | System.out.println("InvocationHandler invoke res: " + JSON.toJSONString(res)); 28 | 29 | this.doAfter(); 30 | 31 | return res; 32 | } 33 | 34 | private void doAfter() { 35 | System.out.println("log this after invoke"); 36 | } 37 | 38 | private void doBefore() { 39 | System.out.println("log this before invoke"); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/proxy/jdk/动态代理/handler/MyInvocationHandler.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.proxy.jdk.动态代理.handler; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | 5 | import java.lang.reflect.InvocationHandler; 6 | import java.lang.reflect.Method; 7 | 8 | /** 9 | * @author nibnait 10 | * @version $Id: MyInvocationHandler.java, v 0.1 2019-09-02 下午7:05 nibnait Exp $$ 11 | */ 12 | public class MyInvocationHandler implements InvocationHandler { 13 | 14 | /** 15 | * 目标对象 16 | */ 17 | private Object target; 18 | 19 | public MyInvocationHandler(Object target) { 20 | this.target = target; 21 | } 22 | 23 | /** 24 | * JDK动态代理的核心 25 | * @param proxy 代理对象 26 | * @param method 目标类的真实方法 27 | * @param params 目标方法参数 28 | * @return 29 | * @throws Throwable 30 | */ 31 | @Override 32 | public Object invoke(Object proxy, Method method, Object[] params) throws Throwable { 33 | System.out.println("调用前 params: " + JSON.toJSONString(params)); 34 | Object result = method.invoke(target, params); 35 | System.out.println("调用后 method: " + method.getName() + ", result: " + result); 36 | return result; 37 | } 38 | } -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/proxy/jdk/静态代理/HelloServiceProxy.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.proxy.jdk.静态代理; 2 | 3 | import cc.tianbin.demo.java.proxy.jdk.HelloService; 4 | 5 | /** 6 | * Created by nibnait on 2020/11/23 7 | */ 8 | public class HelloServiceProxy implements HelloService { 9 | private HelloService helloService; 10 | 11 | public HelloServiceProxy(HelloService helloService) { 12 | this.helloService = helloService; 13 | } 14 | 15 | @Override 16 | public void sayHello() { 17 | helloService.sayHello(); 18 | } 19 | 20 | @Override 21 | public void speak(String word) { 22 | helloService.speak(word); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/proxy/jdk/静态代理/Main.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.proxy.jdk.静态代理; 2 | 3 | import org.junit.Test; 4 | import cc.tianbin.demo.java.proxy.jdk.HelloServiceImpl; 5 | 6 | /** 7 | * Created by nibnait on 2020/11/23 8 | */ 9 | public class Main { 10 | 11 | @Test 12 | public void testCase() { 13 | HelloServiceProxy helloServiceProxy = new HelloServiceProxy(new HelloServiceImpl()); 14 | 15 | helloServiceProxy.sayHello(); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/spi/README.md: -------------------------------------------------------------------------------- 1 | > Service provider interface(SPl) is an APl intended to be implemented or extended by a third party. 2 | > It can be used to enable framework extension and replaceable components 3 | 4 | ## Java SPI 5 | 6 | > ServiceLoader.load(Log.class); 7 | > META-lNF/services/ 8 | 9 | 源码阅读:[Main_Java_SPI.java](./javaSPI/Main_Java_SPI.java) 10 | 11 | 比如经典数据库驱动实例的获取 [JdbcDemo.java](./javaSPI/JdbcDemo.java) 12 | 1. 接口是什么:JDK定义的java.sql.Driver 13 | 2. 那实现类是什么呢? 14 | 实现类是由不同的数据库厂商定义的MySQL Oracle Sql Server等 15 | 3. 约定优于配置的体现 16 | META-lNF/services/java.sql.Driver 接口名称 里面写具体的实现类 17 | 4. 到底在哪里根据接口选择具体的实现类实例? 18 | jdbc连接数据库,需要连接不同的数据库,获取到不同的 connection 19 | 因为不同的数据库需要使用的连接是不一样的,而这个 connection 的获取是根据 driver 的不同而得来的 20 | 21 | 总结:**其实就是根据一个接口,找不同的实现类实例[是可以自定义的,只需要按照约定优于配置的方式定义即可]** 22 | 23 | ## Dubbo SPI 24 | 25 | > ExtensionLoader.getExtensionLoader(DistributedArchitecture.class) 26 | > - META-lNF/dubbo/ 27 | > - META-lNF/dubbo/internal 28 | > - META-lNF/services/ 29 | 30 | 源码阅读: [Main_Dubbo_SPI.java](./dubboSPI/Main_Dubbo_SPI.java) 31 | 32 | 33 | 34 | ![](https://cn.dubbo.apache.org/imgs/dev/dubbo-framework.jpg) 35 | 36 | 配置文件,支持 kv配置。 37 | 38 | ## Spring SPI 39 | > SpringFactoriesLoader.loadFactories(SpringXXXListener.class, classLoader); 40 | > META-lNF/spring.factories 41 | 42 | 源码阅读:[Main_Spring_SPI.java](./springSPI/Main_Spring_SPI.java) 43 | 44 | 业务代码,也可以实现一些 Spring 内部的接口,然后在 spring.factories 里添加下配置。即可被 spring 框架扫描到。 45 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/spi/dubboSPI/DistributedArchitecture.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.spi.dubboSPI; 2 | 3 | import org.apache.dubbo.common.extension.SPI; 4 | 5 | /** 6 | * Created by nibnait on 2023/03/25 7 | */ 8 | @SPI("dubbo") 9 | public interface DistributedArchitecture { 10 | void solve(String msg); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/spi/dubboSPI/impl/DubboImpl.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.spi.dubboSPI.impl; 2 | 3 | import cc.tianbin.common.util.LogUtil; 4 | import cc.tianbin.demo.java.spi.dubboSPI.DistributedArchitecture; 5 | 6 | /** 7 | * Created by nibnait on 2023/03/25 8 | */ 9 | public class DubboImpl implements DistributedArchitecture { 10 | @Override 11 | public void solve(String msg) { 12 | LogUtil.log("dubbo solve: {}", msg); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/spi/dubboSPI/impl/ServiceMeshImpl.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.spi.dubboSPI.impl; 2 | 3 | import cc.tianbin.common.util.LogUtil; 4 | import cc.tianbin.demo.java.spi.dubboSPI.DistributedArchitecture; 5 | 6 | /** 7 | * Created by nibnait on 2023/03/25 8 | */ 9 | public class ServiceMeshImpl implements DistributedArchitecture { 10 | @Override 11 | public void solve(String msg) { 12 | LogUtil.log("service mesh solve: {}", msg); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/spi/dubboSPI/impl/SpringCloudImpl.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.spi.dubboSPI.impl; 2 | 3 | import cc.tianbin.common.util.LogUtil; 4 | import cc.tianbin.demo.java.spi.dubboSPI.DistributedArchitecture; 5 | 6 | /** 7 | * Created by nibnait on 2023/03/25 8 | */ 9 | public class SpringCloudImpl implements DistributedArchitecture { 10 | 11 | @Override 12 | public void solve(String msg) { 13 | LogUtil.log("spring cloud solve: {}", msg); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/spi/javaSPI/JdbcDemo.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.spi.javaSPI; 2 | 3 | import cc.tianbin.common.util.LogUtil; 4 | 5 | import java.sql.Connection; 6 | import java.sql.DriverManager; 7 | import java.sql.ResultSet; 8 | import java.sql.Statement; 9 | 10 | /** 11 | * Created by nibnait on 2023/03/25 12 | */ 13 | public class JdbcDemo { 14 | 15 | /** 16 | * @see DriverManager#loadInitialDrivers() 17 | */ 18 | public static void main(String[] args) throws Exception { 19 | 20 | Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test", "root", "root"); 21 | LogUtil.printf("MySQL Connected."); 22 | Statement statement = connection.createStatement(); 23 | String sql = "select * from user"; 24 | ResultSet resultSet = statement.executeQuery(sql); 25 | while (resultSet.next()) { 26 | Integer id = resultSet.getInt("id"); 27 | String username = resultSet.getString("name"); 28 | String password = resultSet.getString("age"); 29 | LogUtil.printf("name: %s, age: %s", username, password); 30 | } 31 | resultSet.close(); 32 | statement.close(); 33 | connection.close(); 34 | } 35 | } -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/spi/javaSPI/Log.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.spi.javaSPI; 2 | 3 | /** 4 | * Created by nibnait on 2023/03/25 5 | */ 6 | public interface Log { 7 | 8 | void print(String content); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/spi/javaSPI/Main_Java_SPI.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.spi.javaSPI; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Iterator; 6 | import java.util.ServiceLoader; 7 | 8 | /** 9 | * Created by nibnait on 2023/03/25 10 | */ 11 | public class Main_Java_SPI { 12 | 13 | /** 14 | * 约定大于配置 15 | * 找到 resources/META-INF/services/ 下的 cc.tianbin.demo.java.spi.javaSPI.Log 文件 16 | 17 | */ 18 | @Test 19 | public void test() { 20 | ServiceLoader serviceLoader = ServiceLoader.load(Log.class); 21 | Iterator iterator = serviceLoader.iterator(); 22 | 23 | /** 24 | * @see Iterator#hasNext() 25 | * @see ServiceLoader.LazyIterator#hasNext() 26 | * @see ServiceLoader.LazyIterator#hasNextService() 27 | */ 28 | while (iterator.hasNext()) { 29 | 30 | /** 31 | * @see Iterator#next() 32 | * @see ServiceLoader.LazyIterator#next() 33 | * @see ServiceLoader.LazyIterator#nextService() 34 | */ 35 | Log log = iterator.next(); 36 | log.print("hello world"); 37 | } 38 | 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/spi/javaSPI/impl/Log4jImpl.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.spi.javaSPI.impl; 2 | 3 | import cc.tianbin.common.util.LogUtil; 4 | import cc.tianbin.demo.java.spi.javaSPI.Log; 5 | 6 | /** 7 | * Created by nibnait on 2023/03/25 8 | */ 9 | public class Log4jImpl implements Log { 10 | @Override 11 | public void print(String content) { 12 | LogUtil.log("Log4j print: \t{}", content); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/spi/javaSPI/impl/LogbackImpl.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.spi.javaSPI.impl; 2 | 3 | import cc.tianbin.common.util.LogUtil; 4 | import cc.tianbin.demo.java.spi.javaSPI.Log; 5 | 6 | /** 7 | * Created by nibnait on 2023/03/25 8 | */ 9 | public class LogbackImpl implements Log { 10 | @Override 11 | public void print(String content) { 12 | LogUtil.log("Logback print: \t{}", content); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/spi/javaSPI/impl/Sfl4jImpl.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.spi.javaSPI.impl; 2 | 3 | import cc.tianbin.common.util.LogUtil; 4 | import cc.tianbin.demo.java.spi.javaSPI.Log; 5 | 6 | /** 7 | * Created by nibnait on 2023/03/25 8 | */ 9 | public class Sfl4jImpl implements Log { 10 | @Override 11 | public void print(String content) { 12 | LogUtil.log("slf4j print: \t{}", content); 13 | } 14 | } -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/spi/springSPI/Main_Spring_SPI.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.spi.springSPI; 2 | 3 | import org.junit.Test; 4 | import org.springframework.context.ApplicationContextInitializer; 5 | import org.springframework.core.io.support.SpringFactoriesLoader; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Created by nibnait on 2023/03/25 11 | */ 12 | public class Main_Spring_SPI { 13 | 14 | /** 15 | * @see SpringFactoriesLoader#loadFactories(Class, ClassLoader) 16 | * @see SpringFactoriesLoader#loadFactoryNames(Class, ClassLoader) 17 | * 18 | */ 19 | @Test 20 | public void test() { 21 | List springXXXListeners = SpringFactoriesLoader.loadFactories(SpringXXXListener.class, Thread.currentThread().getContextClassLoader()); 22 | for (SpringXXXListener listener : springXXXListeners) { 23 | listener.run(); 24 | } 25 | 26 | } 27 | 28 | @Test 29 | public void 扩展SpringSPI() { 30 | List initializers = SpringFactoriesLoader.loadFactories(ApplicationContextInitializer.class, Thread.currentThread().getContextClassLoader()); 31 | 32 | System.out.println(initializers.size()); 33 | for (ApplicationContextInitializer initializer : initializers) { 34 | System.out.println(initializer); 35 | } 36 | 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/spi/springSPI/SpringApplicationContextInitializer.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.spi.springSPI; 2 | 3 | import cc.tianbin.common.util.LogUtil; 4 | import org.springframework.context.ApplicationContextInitializer; 5 | import org.springframework.context.ConfigurableApplicationContext; 6 | 7 | /** 8 | * Created by nibnait on 2023/03/25 9 | */ 10 | public class SpringApplicationContextInitializer implements ApplicationContextInitializer { 11 | 12 | @Override 13 | public void initialize(ConfigurableApplicationContext applicationContext) { 14 | LogUtil.log("spring 启动过程中,干一些自己的事情"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/spi/springSPI/SpringXXXListener.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.spi.springSPI; 2 | 3 | /** 4 | * Created by nibnait on 2023/03/25 5 | */ 6 | public interface SpringXXXListener { 7 | 8 | void run(); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/spi/springSPI/impl/SpringXXXListenerImpl01.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.spi.springSPI.impl; 2 | 3 | import cc.tianbin.common.util.LogUtil; 4 | import cc.tianbin.demo.java.spi.springSPI.SpringXXXListener; 5 | 6 | /** 7 | * Created by nibnait on 2023/03/25 8 | */ 9 | public class SpringXXXListenerImpl01 implements SpringXXXListener { 10 | @Override 11 | public void run() { 12 | LogUtil.log("SpringXXXListenerImpl01"); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/spi/springSPI/impl/SpringXXXListenerImpl02.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.spi.springSPI.impl; 2 | 3 | import cc.tianbin.common.util.LogUtil; 4 | import cc.tianbin.demo.java.spi.springSPI.SpringXXXListener; 5 | 6 | /** 7 | * Created by nibnait on 2023/03/25 8 | */ 9 | public class SpringXXXListenerImpl02 implements SpringXXXListener { 10 | @Override 11 | public void run() { 12 | LogUtil.log("SpringXXXListenerImpl01"); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/基本数据类型/BooleanTest.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.基本数据类型; 2 | 3 | import junit.framework.TestCase; 4 | import org.junit.Test; 5 | 6 | public class BooleanTest extends TestCase { 7 | 8 | @Test 9 | public void testParseBoolean() { 10 | boolean b = Boolean.parseBoolean("1"); 11 | System.out.println(b); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/基本数据类型/ByteTest.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.基本数据类型; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * Created by nibnait on 2021/12/09 7 | */ 8 | public class ByteTest { 9 | 10 | @Test 11 | public void equals() { 12 | Byte b6 = (byte) 6; 13 | Integer i6 = 6; 14 | System.out.println(b6.equals(i6)); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/基本数据类型/DoubleTest.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.基本数据类型; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * Created by nibnait on 2021/06/02 7 | */ 8 | public class DoubleTest { 9 | 10 | @Test 11 | public void test01() { 12 | String s = "19.9"; 13 | Double d = Double.valueOf(s); 14 | System.out.println(d); 15 | } 16 | 17 | @Test 18 | public void test02() { 19 | double d = 19.9; 20 | 21 | double v = d * 100; 22 | System.out.println(v); 23 | 24 | int i = (int)v; 25 | System.out.println(i); 26 | 27 | int d1 = 1989; 28 | double d2 = (double) d1 / 100; 29 | System.out.println(d2); 30 | 31 | d1 = 1990; 32 | d2 = (double) d1 / 100; 33 | System.out.println(d2); 34 | 35 | } 36 | 37 | @Test 38 | public void test03() { 39 | double d = 19.9; 40 | 41 | double v = d * 0.5; 42 | System.out.println(v); 43 | 44 | int i = (int)v; 45 | System.out.println(i); 46 | 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/基本数据类型/MathTest.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.基本数据类型; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * Created by nibnait on 2022/01/03 7 | */ 8 | public class MathTest { 9 | 10 | @Test 11 | public void ceil() { 12 | int ceil = (int) Math.ceil(2 * 0.9); 13 | System.out.println(ceil); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/AQS源码阅读/LockAndAqs.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.并发.AQS源码阅读; 2 | 3 | import java.util.concurrent.locks.ReentrantLock; 4 | 5 | /** 6 | * Created by nibnait on 2023/02/01 7 | */ 8 | public class LockAndAqs { 9 | 10 | private static ReentrantLock lock = new ReentrantLock(); 11 | 12 | public static void main(String[] args) { 13 | 14 | 15 | try { 16 | lock.lock(); 17 | } finally { 18 | lock.unlock(); 19 | } 20 | 21 | 22 | 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/AQS源码阅读/ReentrantLock可重入锁_非公平锁.md: -------------------------------------------------------------------------------- 1 | 2 | ## lock (sync.lock()) 3 | 4 | ```java 5 | final void lock() { 6 | if (compareAndSetState(0, 1)) 7 | setExclusiveOwnerThread(Thread.currentThread()); 8 | else 9 | acquire(1); 10 | } 11 | 12 | public final void acquire(int arg) { 13 | if (!tryAcquire(arg) && 14 | acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) 15 | selfInterrupt(); 16 | } 17 | 18 | protected final boolean tryAcquire(int acquires) { 19 | return nonfairTryAcquire(acquires); 20 | } 21 | 22 | final boolean nonfairTryAcquire(int acquires) { 23 | final Thread current = Thread.currentThread(); 24 | int c = getState(); 25 | if (c == 0) { 26 | // c == 0 && casState(0, 1) 成功 ==> 抢锁成功。否则直接入队。 27 | if (compareAndSetState(0, acquires)) { 28 | setExclusiveOwnerThread(current); 29 | return true; 30 | } 31 | } 32 | else if (current == getExclusiveOwnerThread()) { 33 | int nextc = c + acquires; 34 | if (nextc < 0) // overflow 35 | throw new Error("Maximum lock count exceeded"); 36 | setState(nextc); 37 | return true; 38 | } 39 | return false; 40 | } 41 | 42 | ``` 43 | 44 | ## unlock(sync.release(1)) 45 | ```java 46 | public void unlock() { 47 | sync.release(1); 48 | } 49 | 50 | 释放锁 没有公平 非公平之分。 51 | 52 | ``` -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/AQS源码阅读/synchronized不可重入锁_非公平锁.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nibnait/algorithms/4d88870d479793b7bcf8418402251acb9498eec9/src/main/java/cc/tianbin/demo/java/并发/AQS源码阅读/synchronized不可重入锁_非公平锁.md -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/JUC/JUC_AQS/CountdownLatchExample.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.并发.JUC.JUC_AQS; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.concurrent.CountDownLatch; 6 | import java.util.concurrent.ExecutorService; 7 | import java.util.concurrent.Executors; 8 | 9 | /** 10 | * Created by nibnait on 2020/11/4 11 | */ 12 | public class CountdownLatchExample { 13 | 14 | /** 15 | * 所有线程自己执行自己的,每个线程 只要调用一次 countDownLatch.countDown(); 计数器就减一 16 | * 走到 countDownLatch.await(); 时,快的线程会等待慢的线程,执行完。 17 | * 再继续往下走。 18 | * 19 | * 或者 当 countDown减到0时,即使慢的线程还没执行完,也会继续往下走。。不等了。。。 20 | * 21 | * @throws InterruptedException 22 | */ 23 | @Test 24 | public void testCase() throws InterruptedException { 25 | int totalThread = 90; 26 | CountDownLatch countDownLatch = new CountDownLatch(totalThread); 27 | 28 | ExecutorService executor = Executors.newCachedThreadPool(); 29 | 30 | for (int i = 0; i < 101; i++) { 31 | int finalI = i; 32 | executor.execute(() -> { 33 | System.out.println("run.." + finalI); 34 | countDownLatch.countDown(); 35 | 36 | System.out.println("after.." + finalI); 37 | }); 38 | } 39 | 40 | countDownLatch.await(); 41 | 42 | System.out.println("...一起落库..."); 43 | executor.shutdown(); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/JUC/JUC_AQS/CyclicBarrierExample.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.并发.JUC.JUC_AQS; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.concurrent.BrokenBarrierException; 6 | import java.util.concurrent.CyclicBarrier; 7 | import java.util.concurrent.ExecutorService; 8 | import java.util.concurrent.Executors; 9 | 10 | /** 11 | * Created by nibnait on 2020/11/4 12 | */ 13 | public class CyclicBarrierExample { 14 | 15 | /** 16 | * cyclicBarrier.await() 之后,线程进入主动等待状态。 17 | * 直到 cyclicBarrier计数器归零。 18 | * 19 | * 主线程 和 线程池中的所有线程继续并发执行 20 | */ 21 | @Test 22 | public void testCase() { 23 | int totalThread = 100; 24 | CyclicBarrier cyclicBarrier = new CyclicBarrier(totalThread); 25 | 26 | ExecutorService executor = Executors.newCachedThreadPool(); 27 | 28 | for (int i = 0; i < totalThread; i++) { 29 | int finalI = i; 30 | executor.execute(() -> { 31 | System.out.print("run.." + finalI + " "); 32 | try { 33 | cyclicBarrier.await(); 34 | } catch (InterruptedException | BrokenBarrierException e) { 35 | e.printStackTrace(); 36 | } 37 | 38 | System.out.println("after.." + finalI); 39 | }); 40 | } 41 | 42 | System.out.println("...一起落库..."); 43 | 44 | executor.shutdown(); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/JUC/JUC_AQS/README.md: -------------------------------------------------------------------------------- 1 | ## CountDownLatch 2 | 3 | 用来控制一个或者多个线程等待多个线程。 4 | 5 | 维护了一个计数器 cnt,每次调用 countDown() 方法会让计数器的值减 1,减到 0 的时候,那些因为调用 await() 方法而在等待的线程就会被唤醒。 6 | 7 | 所有线程自己执行自己的,每个线程 只要调用一次 countDownLatch.countDown(); 计数器就减一 8 | 走到 countDownLatch.await(); 时,快的线程会等待慢的线程,执行完。 9 | 再继续往下走。 10 | 11 | 或者 当 countDown减到0时,即使慢的线程还没执行完,也会继续往下走。。不等了。。。 12 | 13 | ## CyclicBarrier 14 | 15 | 用来控制多个线程互相等待,只有当多个线程都到达时,这些线程才会继续执行。 16 | 17 | 和 CountdownLatch 相似,都是通过维护计数器来实现的。线程执行 await() 方法之后计数器会减 1,并进行等待,直到计数器为 0,所有调用 await() 方法而在等待的线程才能继续执行。 18 | 19 | CyclicBarrier 和 CountdownLatch 的一个区别是,CyclicBarrier 的计数器通过调用 reset() 方法可以循环使用,所以它才叫做循环屏障。 20 | 21 | cyclicBarrier.await() 之后,线程进入主动等待状态。 22 | 直到 cyclicBarrier计数器归零。 23 | 24 | 主线程 和 线程池中的所有线程继续并发执行 25 | 26 | ## Semaphore 27 | 28 | Semaphore 类似于操作系统中的信号量,可以控制对互斥资源的访问线程数。 29 | 30 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/JUC/JUC_AQS/mylock/MyLockTest.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.并发.JUC.JUC_AQS.mylock; 2 | 3 | import cc.tianbin.common.util.LogUtil; 4 | 5 | import static cc.tianbin.demo.java.并发.JUC.JUC_AQS.mylock.MyLock.MY_LOCK_NAME; 6 | 7 | /** 8 | * Created by nibnait on 2023/02/01 9 | */ 10 | public class MyLockTest { 11 | 12 | private static MyLock lock = new MyLock(); 13 | 14 | /** 15 | * 自定义一把锁 16 | * 设计一把自定义的锁你高要多久?需求如下: 17 | * 1.排它锁,只有线程 name 以"myLock”开头的才能获取剑 18 | * 2.不支持重入,喜欢一次藏够了。 19 | * 3.支持尝试加锁 20 | * 4,支持超时尝试加锁 21 | * 5.支持可中衙加锁 22 | * 6.支wait notify功能 23 | * 7.其他不以“myLock”开头的线程名称,一律拒之门外。 24 | */ 25 | public static void main(String[] args) { 26 | 27 | Thread t1 = new Thread(() -> { 28 | testLock(); 29 | }); 30 | 31 | Thread t2 = new Thread(() -> { 32 | testLock(); 33 | }); 34 | 35 | t1.setName(MY_LOCK_NAME); 36 | // t1.setName("xx" + MY_LOCK_NAME); 37 | t2.setName("xxx"); 38 | 39 | t1.start(); 40 | t2.start(); 41 | 42 | } 43 | 44 | private static void testLock() { 45 | lock.lock(); 46 | 47 | try { 48 | LogUtil.log("{} 拿到了锁", Thread.currentThread().getName()); 49 | } finally { 50 | lock.unlock(); 51 | } 52 | } 53 | 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/JUC/JUC_demo/Cache.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.并发.JUC.JUC_demo; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import java.util.concurrent.locks.Lock; 6 | import java.util.concurrent.locks.ReadWriteLock; 7 | import java.util.concurrent.locks.ReentrantReadWriteLock; 8 | 9 | /** 10 | * 基于ReentrantReadWriteLock 实现的缓存类 11 | * 12 | * @author nibnait 13 | * @version $Id: Cache.java, v 0.1 2019-08-31 下午8:19 nibnait Exp $$ 14 | */ 15 | class Cache { 16 | final Map map = new HashMap<>(); 17 | final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); 18 | // 读锁 19 | final Lock readLock = readWriteLock.readLock(); 20 | // 写锁 21 | final Lock writeLock = readWriteLock.writeLock(); 22 | 23 | // 读缓存 24 | V get(K key) { 25 | readLock.lock(); 26 | try { 27 | return map.get(key); 28 | } finally { 29 | readLock.unlock(); 30 | } 31 | } 32 | 33 | // 写缓存 34 | V put(K key, V v) { 35 | writeLock.lock(); 36 | try { 37 | return map.put(key, v); 38 | } finally { 39 | writeLock.unlock(); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/JUC/JUC_other/ForkJoinExample.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.并发.JUC.JUC_other; 2 | 3 | import java.util.concurrent.RecursiveTask; 4 | 5 | /** 6 | * Created by nibnait on 2020/11/5 7 | */ 8 | public class ForkJoinExample extends RecursiveTask { 9 | 10 | private final int threshold = 5; 11 | private int first; 12 | private int last; 13 | 14 | public ForkJoinExample(int first, int last) { 15 | this.first = first; 16 | this.last = last; 17 | } 18 | 19 | @Override 20 | protected Integer compute() { 21 | int result = 0; 22 | if (last - first <= threshold) { 23 | // 任务足够小则直接计算 24 | for (int i = first; i <= last; i++) { 25 | result += i; 26 | } 27 | } else { 28 | // 拆分成小任务 29 | int middle = first + (last - first) / 2; 30 | ForkJoinExample leftTask = new ForkJoinExample(first, middle); 31 | ForkJoinExample rightTask = new ForkJoinExample(middle + 1, last); 32 | leftTask.fork(); 33 | rightTask.fork(); 34 | result = leftTask.join() + rightTask.join(); 35 | } 36 | return result; 37 | } 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/JUC/JUC_other/FutureTaskExample.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.并发.JUC.JUC_other; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.concurrent.Callable; 6 | import java.util.concurrent.ExecutionException; 7 | import java.util.concurrent.FutureTask; 8 | 9 | /** 10 | * Created by nibnait on 2020/11/4 11 | */ 12 | public class FutureTaskExample { 13 | 14 | @Test 15 | public void testCase() throws ExecutionException, InterruptedException { 16 | 17 | FutureTask futureTask = new FutureTask<>(new Callable() { 18 | @Override 19 | public Integer call() throws Exception { 20 | int result = 0; 21 | for (int i = 0; i < 100; i++) { 22 | Thread.sleep(10); 23 | result += i; 24 | } 25 | return result; 26 | } 27 | }); 28 | 29 | Thread computeThread = new Thread(futureTask); 30 | computeThread.start(); 31 | 32 | Thread otherThread = new Thread(() -> { 33 | System.out.println("other task is running..."); 34 | try { 35 | Thread.sleep(1000); 36 | } catch (InterruptedException e) { 37 | e.printStackTrace(); 38 | } 39 | }); 40 | otherThread.start(); 41 | 42 | System.out.println(futureTask.get()); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/JUC/JUC_other/ProducerConsumer.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.并发.JUC.JUC_other; 2 | 3 | import java.util.concurrent.ArrayBlockingQueue; 4 | import java.util.concurrent.BlockingQueue; 5 | 6 | /** 7 | * 使用 BlockingQueue 实现生产者消费者问题 8 | * 9 | * Created by nibnait on 2020/11/5 10 | */ 11 | public class ProducerConsumer { 12 | 13 | private static BlockingQueue queue = new ArrayBlockingQueue<>(5); 14 | 15 | static class Producer extends Thread { 16 | @Override 17 | public void run() { 18 | try { 19 | System.out.println("produce.."); 20 | queue.put("product"); 21 | } catch (InterruptedException e) { 22 | e.printStackTrace(); 23 | } 24 | } 25 | } 26 | 27 | static class Consumer extends Thread { 28 | 29 | @Override 30 | public void run() { 31 | try { 32 | String product = queue.take(); 33 | 34 | System.out.println("consume.." + product); 35 | } catch (InterruptedException e) { 36 | e.printStackTrace(); 37 | } 38 | } 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/JUC/JUC_other/README.md: -------------------------------------------------------------------------------- 1 | ## FutureTask 2 | 3 | 在介绍 Callable 时我们知道它可以有返回值,返回值通过 Future 进行封装。FutureTask 实现了 RunnableFuture 接口,该接口继承自 Runnable 和 Future 接口,这使得 FutureTask 既可以当做一个任务执行,也可以有返回值。 4 | 5 | ```java 6 | public class FutureTask implements RunnableFuture 7 | ``` 8 | 9 | ```java 10 | public interface RunnableFuture extends Runnable, Future 11 | ``` 12 | 13 | FutureTask 可用于异步获取执行结果或取消执行任务的场景。当一个计算任务需要执行很长时间,那么就可以用 FutureTask 来封装这个任务,主线程在完成自己的任务之后再去获取结果。 14 | 15 | 16 | ## BlockingQueue 17 | 18 | java.util.concurrent.BlockingQueue 接口有以下阻塞队列的实现: 19 | 20 | - **FIFO 队列** :LinkedBlockingQueue、ArrayBlockingQueue(固定长度) 21 | - **优先级队列** :PriorityBlockingQueue 22 | 23 | 提供了阻塞的 take() 和 put() 方法:如果队列为空 take() 将阻塞,直到队列中有内容;如果队列为满 put() 将阻塞,直到队列有空闲位置。 24 | 25 | ## ForkJoin 26 | 27 | 主要用于并行计算中,和 MapReduce 原理类似,都是把大的计算任务拆分成多个小任务并行计算。 28 | 29 | ForkJoin 使用 ForkJoinPool 来启动,它是一个特殊的线程池,线程数量取决于 CPU 核数。 30 | 31 | ```java 32 | public class ForkJoinPool extends AbstractExecutorService 33 | ``` 34 | 35 | ForkJoinPool 实现了工作窃取算法来提高 CPU 的利用率。每个线程都维护了一个双端队列,用来存储需要执行的任务。工作窃取算法允许空闲的线程从其它线程的双端队列中窃取一个任务来执行。窃取的任务必须是最晚的任务,避免和队列所属线程发生竞争。 -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nibnait/algorithms/4d88870d479793b7bcf8418402251acb9498eec9/src/main/java/cc/tianbin/demo/java/并发/README.md -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/thread_demo/ThreadDemo1.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.并发.thread_demo; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * Created by nibnait on 2023/03/06 7 | */ 8 | public class ThreadDemo1 extends Thread { 9 | 10 | public static void main(String[] args) { 11 | ThreadDemo1 thread = new ThreadDemo1(); 12 | 13 | thread.start(); 14 | } 15 | 16 | @Override 17 | public void run() { 18 | System.out.println("hello world"); 19 | } 20 | 21 | @Test 22 | public void test2() { 23 | Thread thread = new Thread(new Runnable() { 24 | @Override 25 | public void run() { 26 | System.out.println("hello world"); 27 | } 28 | }); 29 | 30 | thread.start(); 31 | } 32 | 33 | @Test 34 | public void test3() { 35 | Thread thread = new Thread(() -> System.out.println("hello world")); 36 | thread.start(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/thread_demo/ThreadDemo2.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.并发.thread_demo; 2 | 3 | /** 4 | * Created by nibnait on 2023/03/06 5 | */ 6 | public class ThreadDemo2 implements Runnable { 7 | 8 | public static void main(String[] args) { 9 | Thread thread = new Thread(new ThreadDemo2()); 10 | 11 | thread.start(); 12 | } 13 | 14 | @Override 15 | public void run() { 16 | System.out.println("hello world"); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/thread_demo/ThreadDemo3.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.并发.thread_demo; 2 | 3 | import java.util.concurrent.Callable; 4 | import java.util.concurrent.ExecutionException; 5 | import java.util.concurrent.FutureTask; 6 | 7 | /** 8 | * Created by nibnait on 2023/03/06 9 | */ 10 | public class ThreadDemo3 implements Callable { 11 | 12 | public static void main(String[] args) throws ExecutionException, InterruptedException { 13 | FutureTask futureTask = new FutureTask<>(new ThreadDemo3()); 14 | Thread thread = new Thread(futureTask); 15 | thread.start(); 16 | String result = futureTask.get(); 17 | System.out.println(result); 18 | } 19 | 20 | @Override 21 | public String call() throws Exception { 22 | return "hello world"; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/thread_demo/ThreadDemo4.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.并发.thread_demo; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.Executors; 5 | 6 | /** 7 | * Created by nibnait on 2023/03/06 8 | */ 9 | public class ThreadDemo4 implements Runnable { 10 | 11 | public static void main(String[] args) { 12 | ExecutorService executorService = Executors.newFixedThreadPool(10); 13 | executorService.execute(new ThreadDemo4()); 14 | 15 | executorService = Executors.newSingleThreadExecutor(); 16 | executorService.execute(new ThreadDemo4()); 17 | } 18 | 19 | @Override 20 | public void run() { 21 | System.out.println("hello world"); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/threadpool/Main.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.并发.threadpool; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.concurrent.*; 6 | 7 | /** 8 | * Created by nibnait on 2023/03/14 9 | */ 10 | public class Main { 11 | 12 | 13 | @Test 14 | public void ThreadPoolExecutor() { 15 | Executors.newSingleThreadExecutor(); 16 | Executors.newFixedThreadPool(1); 17 | 18 | 19 | ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 1, 20 | 0L, TimeUnit.MILLISECONDS, 21 | new LinkedBlockingQueue(), 22 | Executors.defaultThreadFactory(), 23 | // ThreadPoolExecutor.defaultHandler 24 | new ThreadPoolExecutor.AbortPolicy()); 25 | 26 | 27 | 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/threadpool/a2_FutureTask.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.并发.threadpool; 2 | 3 | import junit.framework.TestCase; 4 | import org.junit.Test; 5 | 6 | import java.util.concurrent.ExecutionException; 7 | import java.util.concurrent.FutureTask; 8 | 9 | /** 10 | * Created by nibnait on 2019-09-01 11 | */ 12 | public class a2_FutureTask extends TestCase { 13 | 14 | 15 | 16 | @Test 17 | public void testFutureTask() throws ExecutionException, InterruptedException { 18 | FutureTask futureTask = new FutureTask<>(() -> 1+2); 19 | Thread thread = new Thread(futureTask); 20 | thread.start(); 21 | Integer result = futureTask.get(); 22 | System.out.println(result); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/threadpool/c1_FockJoinDemo.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.并发.threadpool; 2 | 3 | import junit.framework.TestCase; 4 | import org.junit.Test; 5 | 6 | import java.util.concurrent.ForkJoinPool; 7 | import java.util.concurrent.RecursiveTask; 8 | 9 | /** 10 | * ForkJoinPool 单机版的MapReduce 11 | *

12 | * 用Fork/Join这个并行计算框架 计算斐波那契数列 13 | * 14 | * Created by nibnait on 2019-09-01 15 | */ 16 | public class c1_FockJoinDemo extends TestCase { 17 | 18 | @Test 19 | public void testMain() { 20 | //创建分治任务线程池 21 | ForkJoinPool fjp = new ForkJoinPool(4); 22 | //创建分治任务 23 | Fibonacci fib = new Fibonacci(30); 24 | //启动分治任务 25 | Integer result = fjp.invoke(fib); 26 | //输出结果 27 | System.out.println(result); 28 | } 29 | 30 | //递归任务 31 | class Fibonacci extends RecursiveTask { 32 | final int n; 33 | 34 | Fibonacci(int n) { 35 | this.n = n; 36 | } 37 | 38 | @Override 39 | protected Integer compute() { 40 | if (n <= 1) { 41 | return n; 42 | } 43 | Fibonacci f1 = new Fibonacci(n - 1); 44 | //创建子任务 45 | f1.fork(); 46 | Fibonacci f2 = new Fibonacci(n - 2); 47 | 48 | //等待子任务结果,并合并结果 49 | return f2.compute() + f1.join(); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/threadpool/让3个线程顺序执行/OddEvenPrint.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.并发.threadpool.让3个线程顺序执行; 2 | 3 | import lombok.SneakyThrows; 4 | import org.junit.Test; 5 | 6 | import java.util.concurrent.CyclicBarrier; 7 | import java.util.concurrent.Semaphore; 8 | 9 | /** 10 | * 两个线程,依次打印奇数、偶数 11 | * Created by nibnait on 2023/02/01 12 | */ 13 | public class OddEvenPrint { 14 | 15 | @Test 16 | public void test2() { 17 | 18 | CyclicBarrier c = new CyclicBarrier(2); 19 | 20 | } 21 | 22 | @Test 23 | public void test1() { 24 | 25 | Semaphore s1 = new Semaphore(1); 26 | Semaphore s2 = new Semaphore(0); 27 | 28 | Thread oddThread = new Thread(new Runnable() { 29 | @SneakyThrows 30 | @Override 31 | public void run() { 32 | for (int i = 1; i <= 100; i += 2) { 33 | s1.acquire(); 34 | System.out.println(i); 35 | s2.release(); 36 | } 37 | } 38 | }); 39 | 40 | Thread evenThread = new Thread(new Runnable() { 41 | @SneakyThrows 42 | @Override 43 | public void run() { 44 | for (int i = 2; i <= 100; i += 2) { 45 | s2.acquire(); 46 | System.out.println(i); 47 | s1.release(); 48 | } 49 | } 50 | }); 51 | 52 | evenThread.start(); 53 | oddThread.start(); 54 | 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/threadpool/让3个线程顺序执行/bThreadMainJoinDemo.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.并发.threadpool.让3个线程顺序执行; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 使用主线程的join方法 7 | * Created by nibnait on 2020/11/27 8 | */ 9 | public class bThreadMainJoinDemo { 10 | 11 | @Test 12 | public void testCase() throws InterruptedException { 13 | 14 | Thread thread1 = new Thread(() -> System.out.println("1. 把冰箱门打开")); 15 | Thread thread2 = new Thread(() -> System.out.println("2. 把大象放进去")); 16 | Thread thread3 = new Thread(() -> System.out.println("3. 把冰箱门关上")); 17 | 18 | System.out.println("thread1.start"); 19 | thread1.start(); 20 | thread1.join(); 21 | 22 | System.out.println("thread2.start"); 23 | thread2.start(); 24 | thread2.join(); 25 | 26 | System.out.println("thread3.start"); 27 | thread3.start(); 28 | thread3.join(); 29 | 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/threadpool/让3个线程顺序执行/eSingleThreadPoolDemo.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.并发.threadpool.让3个线程顺序执行; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.concurrent.ExecutorService; 6 | import java.util.concurrent.Executors; 7 | 8 | /** 9 | * 单线程池 10 | * Created by nibnait on 2020/11/27 11 | */ 12 | public class eSingleThreadPoolDemo { 13 | 14 | @Test 15 | public void testCase() { 16 | 17 | ExecutorService executor = Executors.newSingleThreadExecutor(); 18 | 19 | Thread thread1 = new Thread(() -> System.out.println("1. 把冰箱门打开")); 20 | Thread thread2 = new Thread(() -> System.out.println("2. 把大象放进去")); 21 | Thread thread3 = new Thread(() -> System.out.println("3. 把冰箱门关上")); 22 | 23 | System.out.println("thread1.start"); 24 | executor.submit(thread1); 25 | System.out.println("thread2.start"); 26 | executor.submit(thread2); 27 | System.out.println("thread3.start"); 28 | executor.submit(thread3); 29 | 30 | executor.shutdown(); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/悲观锁vs乐观锁/CAS/AtomicIntegerExample.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.并发.悲观锁vs乐观锁.CAS; 2 | 3 | import java.util.concurrent.atomic.AtomicInteger; 4 | 5 | /** 6 | * Created by nibnait on 2020/11/8 7 | */ 8 | public class AtomicIntegerExample { 9 | 10 | public static void main(String[] args) { 11 | AtomicInteger atomicInteger; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/悲观锁vs乐观锁/reentrantLock/LockExample.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.并发.悲观锁vs乐观锁.reentrantLock; 2 | 3 | import java.util.concurrent.locks.Lock; 4 | import java.util.concurrent.locks.ReentrantLock; 5 | 6 | public class LockExample { 7 | 8 | private Lock lock = new ReentrantLock(); 9 | 10 | public void func() { 11 | lock.lock(); 12 | try { 13 | for (int i = 0; i < 10; i++) { 14 | System.out.print(i + " "); 15 | } 16 | } finally { 17 | lock.unlock(); // 确保释放锁,从而避免发生死锁。 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/悲观锁vs乐观锁/reentrantLock/Main.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.并发.悲观锁vs乐观锁.reentrantLock; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.concurrent.ExecutorService; 6 | import java.util.concurrent.Executors; 7 | import java.util.concurrent.locks.ReentrantLock; 8 | import java.util.concurrent.locks.ReentrantReadWriteLock; 9 | 10 | public class Main { 11 | 12 | public static void main(String[] args) { 13 | ReentrantLock reentrantLock; 14 | 15 | ReentrantReadWriteLock reentrantReadWriteLock; 16 | } 17 | 18 | @Test 19 | public void testCase1() { 20 | LockExample lockExample = new LockExample(); 21 | 22 | ExecutorService executorService = Executors.newCachedThreadPool(); 23 | executorService.execute(() -> {lockExample.func();}); 24 | executorService.execute(() -> {lockExample.func();}); 25 | } 26 | 27 | @Test 28 | public void testCase2() { 29 | LockExample lockExample = new LockExample(); 30 | LockExample lockExample2 = new LockExample(); 31 | 32 | ExecutorService executorService = Executors.newCachedThreadPool(); 33 | executorService.execute(() -> {lockExample.func();}); 34 | executorService.execute(() -> {lockExample2.func();}); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/悲观锁vs乐观锁/reentrantLock/线程间的协作/JoinExample.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.并发.悲观锁vs乐观锁.reentrantLock.线程间的协作; 2 | 3 | public class JoinExample { 4 | static class A extends Thread { 5 | @Override 6 | public void run() { 7 | System.out.println("A"); 8 | } 9 | } 10 | 11 | static class B extends Thread { 12 | 13 | private A a; 14 | 15 | B(A a) { 16 | this.a = a; 17 | } 18 | 19 | @Override 20 | public void run() { 21 | try { 22 | a.join(); 23 | } catch (InterruptedException e) { 24 | e.printStackTrace(); 25 | } 26 | System.out.println("B"); 27 | } 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/悲观锁vs乐观锁/reentrantLock/线程间的协作/README.md: -------------------------------------------------------------------------------- 1 | 当多个线程可以一起工作去解决某个问题时,如果某些部分必须在其它部分之前完成,那么就需要对线程进行协调。 2 | 3 | ## join() 4 | 5 | 在线程中调用另一个线程的 join() 方法,会将当前线程挂起,而不是忙等待,直到目标线程结束。 6 | 7 | 对于以下代码,虽然 b 线程先启动,但是因为在 b 线程中调用了 a 线程的 join() 方法,b 线程会等待 a 线程结束才继续执行,因此最后能够保证 a 线程的输出先于 b 线程的输出。 8 | 9 | ## wait() notify() notifyAll() 10 | 11 | 调用 wait() 使得线程等待某个条件满足,线程在等待时会被挂起,当其他线程的运行使得这个条件满足时,其它线程会调用 notify() 或者 notifyAll() 来唤醒挂起的线程。 12 | 13 | 它们都属于 Object 的一部分,而不属于 Thread。 14 | 15 | 只能用在同步方法或者同步控制块中使用,否则会在运行时抛出 IllegalMonitorStateException。 16 | 17 | 使用 wait() 挂起期间,线程会释放锁。这是因为,如果没有释放锁,那么其它线程就无法进入对象的同步方法或者同步控制块中,那么就无法执行 notify() 或者 notifyAll() 来唤醒挂起的线程,造成死锁。 18 | 19 | **wait() 和 sleep() 的区别** 20 | 21 | - wait() 是 Object 的方法,而 sleep() 是 Thread 的静态方法; 22 | - wait() 会释放锁,sleep() 不会。 23 | 24 | ## await() signal() signalAll() 25 | 26 | java.util.concurrent 类库中提供了 Condition 类来实现线程之间的协调,可以在 Condition 上调用 await() 方法使线程等待,其它线程调用 signal() 或 signalAll() 方法唤醒等待的线程。 27 | 28 | 相比于 wait() 这种等待方式,await() 可以指定等待的条件,因此更加灵活。 29 | 30 | 使用 Lock 来获取一个 Condition 对象。 -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/悲观锁vs乐观锁/reentrantLock/线程间的协作/WaitNotifyExample.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.并发.悲观锁vs乐观锁.reentrantLock.线程间的协作; 2 | 3 | public class WaitNotifyExample { 4 | 5 | public synchronized void runNotifyAll() { 6 | System.out.println("notifyAll"); 7 | notifyAll(); 8 | } 9 | 10 | public synchronized void runNotify() { 11 | System.out.println("notify"); 12 | notify(); 13 | } 14 | 15 | public synchronized void runWait() { 16 | try { 17 | wait(); 18 | } catch (InterruptedException e) { 19 | e.printStackTrace(); 20 | } 21 | System.out.println("wait"); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/并发/悲观锁vs乐观锁/synchronize/SynchronizedExample.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.并发.悲观锁vs乐观锁.synchronize; 2 | 3 | public class SynchronizedExample { 4 | 5 | /** 6 | * 只锁 本对象的 func1方法 7 | */ 8 | public void func1() { 9 | synchronized (this) { 10 | for (int i = 0; i < 100; i++) { 11 | System.out.print(i + " "); 12 | } 13 | System.out.println("\nover"); 14 | } 15 | } 16 | 17 | /** 18 | * 只锁 本对象的 func1方法 19 | */ 20 | public synchronized void func2() { 21 | for (int i = 0; i < 100; i++) { 22 | System.out.print(i + " "); 23 | } 24 | System.out.println("\nover"); 25 | } 26 | 27 | /** 28 | * 锁 SynchronizedExample.class 这个类的所有对象的 func3 29 | */ 30 | public synchronized static void func3() { 31 | for (int i = 0; i < 100; i++) { 32 | System.out.print(i + " "); 33 | } 34 | System.out.println("\nover"); 35 | } 36 | 37 | /** 38 | * 锁 SynchronizedExample.class 这个类的所有对象的 func4 39 | */ 40 | public void func4() { 41 | synchronized (SynchronizedExample.class) { 42 | for (int i = 0; i < 100; i++) { 43 | System.out.print(i + " "); 44 | } 45 | } 46 | System.out.println("\nover"); 47 | } 48 | 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/异常/Main.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.异常; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * Created by nibnait on 2020/11/24 7 | */ 8 | public class Main { 9 | 10 | @Test 11 | public void testThrowable() throws Throwable { 12 | 13 | throw new Throwable(); 14 | 15 | } 16 | 17 | @Test 18 | public void testException() throws Exception { 19 | 20 | throw new Exception(); 21 | } 22 | 23 | 24 | @Test 25 | public void testError() { 26 | 27 | throw new Error(); 28 | } 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/异常/README.md: -------------------------------------------------------------------------------- 1 | Java 中常见的异常类型包括以下几种: 2 | 3 | - Checked Exception:可检查异常,必须在代码中进行处理或声明抛出。例如:IOException,ClassNotFoundException。 4 | - Unchecked Exception:非检查异常,也称为运行时异常。通常是程序员的错误或者环境导致的问题,不需要显式地处理或声明抛出。例如:NullPointerException,ArrayIndexOutOfBoundsException。 5 | - Error:表示严重的错误,不应该被程序员处理或捕获。例如:OutOfMemoryError,StackOverflowError。 6 | 7 | 常见的 Java 异常类型可以归为以下几类: 8 | 9 | 空指针异常(NullPointerException):当尝试访问空对象时抛出。 10 | 类型转换异常(ClassCastException):当试图将一个对象强制转换为不兼容的类型时抛出。 11 | 数组越界异常(ArrayIndexOutOfBoundsException):当尝试访问数组中不存在的元素时抛出。 12 | 算术异常(ArithmeticException):当出现除零或者其它算术错误时抛出。 13 | 文件 IO 异常(IOException):当文件 I/O 操作失败时抛出。 14 | SQL 异常(SQLException):当数据库操作失败时抛出。 15 | 并发修改异常(ConcurrentModificationException):当尝试在迭代时修改集合时抛出。 16 | 线程中断异常(InterruptedException):当线程被中断时抛出。 17 | 类未找到异常(ClassNotFoundException):当试图加载类时找不到类定义时抛出。 18 | 以上仅是 Java 异常类型的一部分,实际上还有很多其它的异常类型,不同的库和框架也可能会定义自己的异常类型。 -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/继承/HelloA.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.继承; 2 | 3 | /** 4 | * Created by nibnait on 2023/03/22 5 | */ 6 | public class HelloA { 7 | 8 | static { 9 | System.out.println("static a"); 10 | } 11 | 12 | { 13 | System.out.println("I'm a class"); 14 | } 15 | 16 | public HelloA() { 17 | System.out.println("hello a"); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/继承/HelloB.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.继承; 2 | 3 | /** 4 | * Created by nibnait on 2023/03/22 5 | */ 6 | public class HelloB extends HelloA { 7 | 8 | static { 9 | System.out.println("static b"); 10 | } 11 | 12 | { 13 | System.out.println("I'm b class"); 14 | } 15 | 16 | public HelloB() { 17 | System.out.println("hello b"); 18 | } 19 | 20 | public static void main(String[] args) { 21 | System.out.println("start"); 22 | 23 | new HelloB(); 24 | 25 | System.out.println("end"); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/集合/List类.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.集合; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.*; 6 | import java.util.concurrent.BlockingQueue; 7 | 8 | /** 9 | * @author nibnait 10 | * @version $Id: List.java, v 0.1 2019-08-15 上午10:58 nibnait Exp $$ 11 | */ 12 | public class List类 { 13 | public static void main(String[] args) { 14 | 15 | Queue queue; 16 | Deque linkedList = new LinkedList(); 17 | linkedList.push(1); 18 | 19 | BlockingQueue blockingQueue; 20 | 21 | AbstractQueue abstractQueue; 22 | PriorityQueue priorityQueue; 23 | 24 | ArrayList arrayList; 25 | 26 | 27 | } 28 | 29 | @Test 30 | public void test01() { 31 | // grow 了几次? 32 | List list = new ArrayList<>(0); 33 | // grow 了几次 34 | // List list = new ArrayList<>(); 35 | list.add(1); 36 | list.add(2); 37 | list.add(3); 38 | list.add(4); 39 | list.add(5); 40 | list.add(6); 41 | list.add(7); 42 | list.add(8); 43 | list.add(9); 44 | list.add(10); 45 | } 46 | 47 | @Test 48 | public void test02() { 49 | // 代码里的一些固定长度的list,可以用。 50 | // 无法对都不能对这份儿list进行 add remove 操作,只能修改单个索引下的值 51 | List list1 = Arrays.asList(); 52 | list1.add(""); 53 | 54 | // 使用场景:一个 if/else 里面需要返回 空list 的时候。 55 | // 使用它,不需要再进行创建对象 56 | List list2 = Collections.emptyList(); 57 | list2.add("a"); 58 | } 59 | } -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/集合/Map类.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.集合; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.*; 6 | import java.util.concurrent.ConcurrentHashMap; 7 | import java.util.concurrent.ConcurrentSkipListMap; 8 | 9 | /** 10 | * @author nibnait 11 | * @version $Id: Map.java, v 0.1 2019-08-12 下午2:16 nibnait Exp $$ 12 | */ 13 | public class Map类 { 14 | public static void main(String[] args) { 15 | Hashtable hashtable; 16 | 17 | LinkedHashMap linkedHashMap; 18 | 19 | HashMap hashMap; 20 | WeakHashMap weakHashMap; 21 | IdentityHashMap identityHashMap; 22 | 23 | EnumMap enumMap; 24 | 25 | TreeMap treeMap; 26 | 27 | ConcurrentHashMap concurrentHashMap; 28 | ConcurrentSkipListMap concurrentSkipListMap; 29 | } 30 | 31 | @Test 32 | public void hashMap() { 33 | HashMap map = new HashMap(); 34 | 35 | map.put(1, 1); 36 | map.put(2, 2); 37 | 38 | map.get(1); 39 | map.remove(1); 40 | 41 | } 42 | 43 | @Test 44 | public void concurrentHashMap() { 45 | ConcurrentHashMap concurrentHashMap = new ConcurrentHashMap(); 46 | 47 | concurrentHashMap.put(1, 1); 48 | } 49 | } -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/java/集合/Set类.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.集合; 2 | 3 | import io.github.nibnait.common.utils.DataUtils; 4 | import org.junit.Test; 5 | 6 | import java.util.HashSet; 7 | import java.util.Set; 8 | 9 | /** 10 | * Created by nibnait on 2022/11/10 11 | */ 12 | public class Set类 { 13 | 14 | @Test 15 | public void test() { 16 | Set set = new HashSet(); 17 | set.add(1); 18 | set.add(222); 19 | set.add(3333); 20 | set.add(4444); 21 | set.add(5555); 22 | set.add(6666); 23 | set.add(7777); 24 | set.add(888); 25 | System.out.println("\n" + DataUtils.toJsonStringArray(set) + "\n"); 26 | 27 | 28 | 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/jvm/GCRoots/README.md: -------------------------------------------------------------------------------- 1 | 哪些可作为GC Roots的对象? 2 | 3 | 根搜索算法是JVM用来的判断对象是否存活的算法,此算法基本思路为通过一系列的“GC Roots”对象作为起始点,从这些节点往下搜索,当一个对象和GC Roots不可达时,则该对象是无用的,可被回收的。 4 | 5 | 在java中,可作为GC Roots的对象有: 6 | 7 | 1. 虚拟机栈(栈帧中的本地变量表)中引用的对象; 8 | 2. 方法区中的类静态属性引用的对象; 9 | 3. 方法区中常量引用的对象; 10 | 4. 本地方法栈中JNI(即一般说的Native方法)中引用的对象 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/jvm/GC优化/HeapOOM.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.jvm.GC优化; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * 测试GC 8 | * 9 | * -Xms1024m -Xmx1024m -Xmn512m -XX:+PrintGCDetails -XX:+UseG1GC 10 | -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/Users/nibnait/Desktop/dump 11 | -verbose:gc 12 | -Xloggc:/Users/nibnait/Desktop/HeapOOM_heap_trace.log 13 | 14 | 15 | 16 | -Xms1024m -Xmx1024m -Xmn512m 17 | -XX:+UseG1GC 18 | -XX:MaxGCPauseMillis=20 19 | -XX:+UnlockExperimentalVMOptions 20 | -XX:InitiatingHeapOccupancyPercent=56 21 | -Xloggc:/Users/nibnait/Desktop/HeapOOM_gc.log 22 | -XX:+PrintGCTimeStamps 23 | -XX:+PrintGCDateStamps 24 | -XX:+PrintGCDetails 25 | -XX:+UseGCLogFileRotation 26 | -XX:NumberOfGCLogFiles=10 27 | -XX:GCLogFileSize=512K 28 | -XX:+HeapDumpOnOutOfMemoryError 29 | -XX:HeapDumpPath=/Users/nibnait/Desktop/HeapOOM_heapdump.hprof 30 | 31 | 32 | * JProfile 33 | * 34 | */ 35 | public class HeapOOM { 36 | 37 | public static void main(String[] args) { 38 | Map map = new HashMap<>(); 39 | for (int i = 0; i < Integer.MAX_VALUE; i++) { 40 | map.put(i, i + ""); 41 | } 42 | 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/jvm/classloader/ClassLoaderDemo.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.jvm.classloader; 2 | 3 | /** 4 | * Created by nibnait on 2020/11/11 5 | */ 6 | public class ClassLoaderDemo { 7 | 8 | public static void main(String[] args) { 9 | System.out.println("ClassLodarDemo 的类加载器 \t" + ClassLoaderDemo.class.getClassLoader()); 10 | System.out.println("ClassLodarDemo 的父类的加载器 \t" + ClassLoaderDemo.class.getClassLoader().getParent()); 11 | System.out.println("ClassLodarDemo 的爷爷类的加载器 \t" + ClassLoaderDemo.class.getClassLoader().getParent().getParent()); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/jvm/classloader/LoadStringDemo.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.jvm.classloader; 2 | 3 | import org.junit.Test; 4 | 5 | import java.net.URL; 6 | import java.net.URLClassLoader; 7 | 8 | /** 9 | * Created by nibnait on 2020/11/11 10 | */ 11 | public class LoadStringDemo { 12 | 13 | @Test 14 | public void testGetAppClassLoaderUrls() { 15 | URLClassLoader systemClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader(); 16 | 17 | URL[] urLs = systemClassLoader.getURLs(); 18 | for (URL url: urLs) { 19 | System.out.println(url); 20 | } 21 | } 22 | 23 | @Test 24 | public void testGetExtClassLoaderUrls() { 25 | URLClassLoader systemClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader().getParent(); 26 | 27 | URL[] urLs = systemClassLoader.getURLs(); 28 | for (URL url: urLs) { 29 | System.out.println(url); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/jvm/classloader/自定义类加载器/LoadDemo.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.jvm.classloader.自定义类加载器; 2 | 3 | /** 4 | * Created by nibnait on 2020/11/11 5 | */ 6 | public class LoadDemo { 7 | 8 | public void test() { 9 | System.out.println("LoadDemo 加载成功"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/netty/Main.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.netty; 2 | 3 | /** 4 | * @author nibnait 5 | * @version $Id: Main.java, v 0.1 2019-08-20 上午10:45 nibnait Exp $$ 6 | */ 7 | public class Main { 8 | public static void main(String[] args) { 9 | 10 | } 11 | } -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/netty/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nibnait/algorithms/4d88870d479793b7bcf8418402251acb9498eec9/src/main/java/cc/tianbin/demo/netty/README.md -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/netty/http/App.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.netty.http; 2 | 3 | /** 4 | * @author nibnait 5 | * @version $Id: AppClient.java, v 0.1 2019-08-19 下午8:33 nibnait Exp $$ 6 | */ 7 | public class App { 8 | public static void main(String[] args) { 9 | System.out.println("HTTP服务器启动!"); 10 | HttpServer.start(); 11 | } 12 | } -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/netty/http/ServerInitializer.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.netty.http; 2 | 3 | import io.netty.channel.ChannelInitializer; 4 | import io.netty.channel.ChannelPipeline; 5 | import io.netty.channel.socket.SocketChannel; 6 | import io.netty.handler.codec.http.HttpServerCodec; 7 | 8 | 9 | /** 10 | * @author nibnait 11 | * @version $Id: ClientInitializer.java, v 0.1 2019-08-19 下午8:44 nibnait Exp $$ 12 | */ 13 | public class ServerInitializer extends ChannelInitializer { 14 | @Override 15 | protected void initChannel(SocketChannel socketChannel) throws Exception { 16 | ChannelPipeline pipeline = socketChannel.pipeline(); 17 | pipeline.addLast(new HttpServerCodec()); //NIO自己的字符编码处理器 18 | pipeline.addLast(new ServerHandler()); 19 | 20 | /* 21 | 管道 22 | 工厂的流水线, 23 | */ 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/netty/rpc/ServerApp.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.netty.rpc; 2 | 3 | import cc.tianbin.demo.netty.rpc.customHandler.ExpRequest; 4 | import cc.tianbin.demo.netty.rpc.customHandler.ExpRequestHandler; 5 | import cc.tianbin.demo.netty.rpc.customHandler.FibRequestHandler; 6 | import cc.tianbin.demo.netty.rpc.server.RPCServer; 7 | 8 | /** 9 | * Created by nibnait on 2019-08-21 10 | */ 11 | public class ServerApp { 12 | 13 | public static void main(String[] args) { 14 | RPCServer server = new RPCServer("localhost", 8888, 2, 16); 15 | server.service("fib", Integer.class, new FibRequestHandler()).service("exp", ExpRequest.class, 16 | new ExpRequestHandler()); 17 | server.start(); 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/netty/rpc/client/request/RPCException.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.netty.rpc.client.request; 2 | 3 | /** 4 | * 定义客户端异常,用于统一抛出RPC错误 5 | * Created by nibnait on 2019-08-21 6 | */ 7 | public class RPCException extends RuntimeException { 8 | private static final long serialVersionUID = 1L; 9 | 10 | public RPCException(String message, Throwable cause) { 11 | super(message, cause); 12 | } 13 | 14 | public RPCException(String message) { 15 | super(message); 16 | } 17 | 18 | public RPCException(Throwable cause) { 19 | super(cause); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/netty/rpc/client/request/RPCRequest.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.netty.rpc.client.request; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | 6 | /** 7 | * RPC请求对象 8 | * Created by nibnait on 2019-08-21 9 | */ 10 | @Data 11 | @AllArgsConstructor 12 | public class RPCRequest { 13 | private String requestId; 14 | private String type; 15 | private Object payload; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/netty/rpc/client/request/RPCResponse.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.netty.rpc.client.request; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | 6 | /** 7 | * RPC响应对象 8 | * Created by nibnait on 2019-08-21 9 | */ 10 | @Data 11 | @AllArgsConstructor 12 | public class RPCResponse { 13 | private String requestId; 14 | private String type; 15 | private Object payload; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/netty/rpc/client/request/RequestId.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.netty.rpc.client.request; 2 | 3 | import java.util.UUID; 4 | 5 | /** 6 | * 请求ID生成器 7 | * Created by nibnait on 2019-08-21 8 | */ 9 | public class RequestId { 10 | public static String next() { 11 | return UUID.randomUUID().toString(); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/netty/rpc/client/request/ResponseRegistry.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.netty.rpc.client.request; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * 响应类型注册中心 8 | * Created by nibnait on 2019-08-21 9 | */ 10 | public class ResponseRegistry { 11 | private static Map> clazzes = new HashMap<>(); 12 | public static void register(String type, Class clazz) { 13 | clazzes.put(type, clazz); 14 | } 15 | public static Class get(String type) { 16 | return clazzes.get(type); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/netty/rpc/customHandler/ExpRequest.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.netty.rpc.customHandler; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * 指数RPC的输入 9 | * Created by nibnait on 2019-08-21 10 | */ 11 | @Data 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class ExpRequest { 15 | private int base; 16 | private int exp; 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/netty/rpc/customHandler/ExpRequestHandler.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.netty.rpc.customHandler; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import cc.tianbin.demo.netty.rpc.server.message.IMessageHandler; 5 | import cc.tianbin.demo.netty.rpc.server.message.MessageOutput; 6 | 7 | /** 8 | * Created by nibnait on 2019-08-21 9 | */ 10 | public class ExpRequestHandler implements IMessageHandler { 11 | 12 | @Override 13 | public void handle(ChannelHandlerContext ctx, String requestId, ExpRequest message) { 14 | int base = message.getBase(); 15 | int exp = message.getExp(); 16 | long start = System.nanoTime(); 17 | long res = 1; 18 | for (int i = 0; i < exp; i++) { 19 | res *= base; 20 | } 21 | long cost = System.nanoTime() - start; 22 | ctx.writeAndFlush(new MessageOutput(requestId, "exp_res", new ExpResponse(res, cost))); 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/netty/rpc/customHandler/ExpResponse.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.netty.rpc.customHandler; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * 指数RPC的输出 9 | * Created by nibnait on 2019-08-21 10 | */ 11 | @Data 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class ExpResponse { 15 | private long value; 16 | private long costInNanos; 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/netty/rpc/customHandler/FibRequestHandler.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.netty.rpc.customHandler; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import cc.tianbin.demo.netty.rpc.server.message.IMessageHandler; 5 | import cc.tianbin.demo.netty.rpc.server.message.MessageOutput; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | /** 11 | * Created by nibnait on 2019-08-21 12 | */ 13 | public class FibRequestHandler implements IMessageHandler { 14 | 15 | private List fibs = new ArrayList<>(); 16 | 17 | { 18 | fibs.add(1L); // fib(0) = 1 19 | fibs.add(1L); // fib(1) = 1 20 | } 21 | 22 | @Override 23 | public void handle(ChannelHandlerContext ctx, String requestId, Integer n) { 24 | for (int i = fibs.size(); i < n + 1; i++) { 25 | long value = fibs.get(i - 2) + fibs.get(i - 1); 26 | fibs.add(value); 27 | } 28 | ctx.writeAndFlush(new MessageOutput(requestId, "fib_res", fibs.get(n))); 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/netty/rpc/server/message/DefaultHandler.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.netty.rpc.server.message; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | 5 | /** 6 | * 找不到类型的消息统一使用默认处理器处理 7 | * Created by nibnait on 2019-08-21 8 | */ 9 | public class DefaultHandler implements IMessageHandler { 10 | 11 | @Override 12 | public void handle(ChannelHandlerContext ctx, String requestId, MessageInput message) { 13 | System.out.println("unrecognized message type=" + message.getType() + " comes"); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/netty/rpc/server/message/IMessageHandler.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.netty.rpc.server.message; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | 5 | /** 6 | * 消息处理器接口,每个自定义服务必须实现handle方法 7 | * Created by nibnait on 2019-08-21 8 | */ 9 | public interface IMessageHandler { 10 | void handle(ChannelHandlerContext ctx, String requestId, T message); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/netty/rpc/server/message/MessageHandlers.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.netty.rpc.server.message; 2 | 3 | import junit.framework.TestCase; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | /** 9 | * Created by nibnait on 2019-08-21 10 | */ 11 | public class MessageHandlers extends TestCase { 12 | 13 | private Map> handlers = new HashMap<>(); 14 | public DefaultHandler defaultHandler = new DefaultHandler(); 15 | 16 | public void register(String type, IMessageHandler handler) { 17 | handlers.put(type, handler); 18 | } 19 | 20 | public IMessageHandler get(String type) { 21 | IMessageHandler handler = handlers.get(type); 22 | return handler; 23 | } 24 | 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/netty/rpc/server/message/MessageInput.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.netty.rpc.server.message; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | 7 | /** 8 | * Created by nibnait on 2019-08-21 9 | */ 10 | @Data 11 | @AllArgsConstructor 12 | public class MessageInput { 13 | 14 | private String type; 15 | private String requestId; 16 | private String payload; 17 | 18 | // 因为我们想直接拿到对象,所以要提供对象的类型参数 19 | public T getPayload(Class clazz) { 20 | if (payload == null) { 21 | return null; 22 | } 23 | return JSON.parseObject(payload, clazz); 24 | } 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/netty/rpc/server/message/MessageOutput.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.netty.rpc.server.message; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | 6 | /** 7 | * Created by nibnait on 2019-08-21 8 | */ 9 | @Data 10 | @AllArgsConstructor 11 | public class MessageOutput { 12 | 13 | private String requestId; 14 | private String type; 15 | private Object payload; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/netty/rpc/server/message/MessageRegistry.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.netty.rpc.server.message; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * 消息类型注册中心 8 | * Created by nibnait on 2019-08-21 9 | */ 10 | public class MessageRegistry { 11 | private Map> clazzes = new HashMap<>(); 12 | 13 | public void register(String type, Class clazz) { 14 | clazzes.put(type, clazz); 15 | } 16 | 17 | public Class get(String type) { 18 | return clazzes.get(type); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/netty/webSocket/client/ClientApp.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.netty.webSocket.client; 2 | 3 | /** 4 | * Created by nibnait on 2019-08-21 5 | */ 6 | public class ClientApp { 7 | 8 | public static void main(String[] args) { 9 | SocketClient.start(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/netty/webSocket/client/ClientHandler.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.netty.webSocket.client; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.SimpleChannelInboundHandler; 5 | 6 | /** 7 | * Created by nibnait on 2019-08-21 8 | */ 9 | public class ClientHandler extends SimpleChannelInboundHandler { 10 | 11 | @Override 12 | protected void channelRead0(ChannelHandlerContext channelHandlerContext, String message) throws Exception { 13 | System.out.println("来自服务端的消息:"+message); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/netty/webSocket/client/ClientInitializer.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.netty.webSocket.client; 2 | 3 | import io.netty.channel.ChannelInitializer; 4 | import io.netty.channel.ChannelPipeline; 5 | import io.netty.channel.socket.SocketChannel; 6 | import io.netty.handler.codec.DelimiterBasedFrameDecoder; 7 | import io.netty.handler.codec.Delimiters; 8 | import io.netty.handler.codec.string.StringDecoder; 9 | import io.netty.handler.codec.string.StringEncoder; 10 | import io.netty.util.CharsetUtil; 11 | 12 | /** 13 | * Created by nibnait on 2019-08-21 14 | */ 15 | public class ClientInitializer extends ChannelInitializer { 16 | 17 | @Override 18 | protected void initChannel(SocketChannel socketChannel) throws Exception { 19 | //添加自己的处理器 20 | ChannelPipeline pipeline = socketChannel.pipeline(); 21 | 22 | //防止TCP粘包,分隔符拆包器 23 | pipeline.addLast(new DelimiterBasedFrameDecoder(1024, Delimiters.lineDelimiter())); 24 | pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8)); 25 | pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8)); 26 | pipeline.addLast(new ClientHandler()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/netty/webSocket/client/SocketClient.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.netty.webSocket.client; 2 | 3 | import io.netty.bootstrap.Bootstrap; 4 | import io.netty.channel.Channel; 5 | import io.netty.channel.nio.NioEventLoopGroup; 6 | import io.netty.channel.socket.nio.NioSocketChannel; 7 | 8 | import java.io.BufferedReader; 9 | import java.io.InputStreamReader; 10 | 11 | /** 12 | * Created by nibnait on 2019-08-20 13 | */ 14 | public class SocketClient { 15 | 16 | public static void start() { 17 | NioEventLoopGroup handler = new NioEventLoopGroup(); 18 | 19 | //创建启动类对象 20 | Bootstrap bootstrap = new Bootstrap(); 21 | bootstrap.group(handler) 22 | .channel(NioSocketChannel.class) 23 | .handler(new ClientInitializer()); 24 | 25 | try { 26 | Channel channel = bootstrap.connect("127.0.0.1", 8866).sync().channel(); 27 | 28 | BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); 29 | while (true) { 30 | channel.writeAndFlush(bufferedReader.readLine() + "\r\n"); 31 | } 32 | 33 | } catch (Exception e) { 34 | e.printStackTrace(); 35 | handler.shutdownGracefully(); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/netty/webSocket/server/ServerApp.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.netty.webSocket.server; 2 | 3 | /** 4 | * @author nibnait 5 | * @version $Id: ClientApp.java, v 0.1 2019-08-19 下午8:33 nibnait Exp $$ 6 | */ 7 | public class ServerApp { 8 | public static void main(String[] args) { 9 | System.out.println("Socket服务器启动!"); 10 | SocketServer.start(); 11 | } 12 | } -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/netty/webSocket/server/ServerInitializer.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.netty.webSocket.server; 2 | 3 | import io.netty.channel.ChannelInitializer; 4 | import io.netty.channel.ChannelPipeline; 5 | import io.netty.channel.socket.SocketChannel; 6 | import io.netty.handler.codec.DelimiterBasedFrameDecoder; 7 | import io.netty.handler.codec.Delimiters; 8 | import io.netty.handler.codec.string.StringDecoder; 9 | import io.netty.handler.codec.string.StringEncoder; 10 | import io.netty.util.CharsetUtil; 11 | 12 | /** 13 | * Created by nibnait on 2019-08-21 14 | */ 15 | public class ServerInitializer extends ChannelInitializer { 16 | 17 | @Override 18 | protected void initChannel(SocketChannel socketChannel) throws Exception { 19 | //添加自己的处理器 20 | ChannelPipeline pipeline = socketChannel.pipeline(); 21 | 22 | //防止TCP粘包,分隔符拆包器 23 | pipeline.addLast(new DelimiterBasedFrameDecoder(1024, Delimiters.lineDelimiter())); 24 | pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8)); 25 | pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8)); 26 | pipeline.addLast(new ServerHandler()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/netty/webSocket/server/SocketServer.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.netty.webSocket.server; 2 | 3 | import io.netty.bootstrap.ServerBootstrap; 4 | import io.netty.channel.nio.NioEventLoopGroup; 5 | import io.netty.channel.socket.nio.NioServerSocketChannel; 6 | 7 | /** 8 | * Created by nibnait on 2019-08-20 9 | */ 10 | public class SocketServer { 11 | 12 | public static void start() { 13 | NioEventLoopGroup accept = new NioEventLoopGroup(); 14 | NioEventLoopGroup handler = new NioEventLoopGroup(); 15 | 16 | //创建启动类对象 17 | ServerBootstrap bootstrap = new ServerBootstrap(); 18 | bootstrap.group(accept, handler) 19 | .channel(NioServerSocketChannel.class) 20 | .childHandler(new ServerInitializer()); 21 | 22 | try { 23 | bootstrap.bind(8866).sync(); 24 | } catch (Exception e) { 25 | e.printStackTrace(); 26 | accept.shutdownGracefully(); 27 | handler.shutdownGracefully(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/cc/tianbin/demo/redis/RateLimiter/README.md: -------------------------------------------------------------------------------- 1 | # RedisRateLimiter 2 | RedisRateLimiter,与Guava RateLimiter功能类似,基于Redis+Lua+令牌桶算法实现的分布式限流器,提供 3 | - 限流 4 | - 流量整形 5 | - 批处理避免Redis热点 6 | 7 | ## 原理 8 | 算法基于令牌桶算法,一种方式是一个线程匀速不断向桶中添加令牌,显而易见这种方式很好资源;另一种则是延迟计算——即在获取时才计算需要加多少令牌,本次需要等多久,如何更新数据等等,这个好处是不需要一个添加令牌的任务,只需要在获取令牌时进行一次计算即可。 9 | 10 | 这里采用第二种方式,由于涉及到多个计算步骤,为了保证整个过程的原子性,就要依靠redis单线程以及可以支持lua脚本执行这个特性了。话不多说,整个lua脚本内容如下(也就是整个获取令牌过程)。 11 | 12 | 限流器的几个关键属性 13 | 14 | storedPermits 当前存储的令牌数 15 | maxPermits 最大可存储的令牌数,设置为限速器的qps 16 | stableIntervalMicros 多久产生一个令牌 17 | nextFreeTicketMicros 下一次可以获取令牌的时间点 18 | 19 | - 令牌桶算法 20 | - 通过延迟计算方式向令牌桶里加入令牌 21 | - 通过Lua脚本和Redis单线程的特性保证操作的原子性 22 | 23 | 24 | 参数 [https://github.com/diracccc/redis-rate-limiter](https://github.com/diracccc/redis-rate-limiter) -------------------------------------------------------------------------------- /src/main/resources/META-INF/dubbo/internal/cc.tianbin.demo.java.spi.dubboSPI.DistributedArchitecture: -------------------------------------------------------------------------------- 1 | dubbo=cc.tianbin.demo.java.spi.dubboSPI.impl.DubboImpl 2 | servicemesh=cc.tianbin.demo.java.spi.dubboSPI.impl.ServiceMeshImpl 3 | springcloud=cc.tianbin.demo.java.spi.dubboSPI.impl.SpringCloudImpl 4 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/services/cc.tianbin.demo.java.spi.javaSPI.Log: -------------------------------------------------------------------------------- 1 | cc.tianbin.demo.java.spi.javaSPI.impl.Log4jImpl 2 | cc.tianbin.demo.java.spi.javaSPI.impl.LogbackImpl 3 | cc.tianbin.demo.java.spi.javaSPI.impl.Sfl4jImpl -------------------------------------------------------------------------------- /src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | cc.tianbin.demo.java.spi.springSPI.SpringXXXListener=\ 2 | cc.tianbin.demo.java.spi.springSPI.impl.SpringXXXListenerImpl01, \ 3 | cc.tianbin.demo.java.spi.springSPI.impl.SpringXXXListenerImpl02 4 | 5 | 6 | org.springframework.context.ApplicationContextInitializer=\ 7 | cc.tianbin.demo.java.spi.springSPI.SpringApplicationContextInitializer -------------------------------------------------------------------------------- /src/main/resources/config/rpc_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "nevermore.service": { 3 | "protocol": "json", 4 | "group": "channel-stable-1" 5 | } 6 | } -------------------------------------------------------------------------------- /src/main/resources/data/graph/characterGraphfilePath.txt: -------------------------------------------------------------------------------- 1 | 10 2 | r s 3 | r v 4 | s w 5 | w t 6 | w x 7 | t u 8 | t x 9 | x u 10 | x y 11 | u y -------------------------------------------------------------------------------- /src/main/resources/data/graph/digitGraph.txt: -------------------------------------------------------------------------------- 1 | 13 2 | 0 5 3 | 4 3 4 | 0 1 5 | 9 12 6 | 6 4 7 | 5 4 8 | 0 2 9 | 11 12 10 | 9 10 11 | 0 6 12 | 7 8 13 | 9 11 14 | 5 3 -------------------------------------------------------------------------------- /src/main/resources/data/graph/tinyCG.txt: -------------------------------------------------------------------------------- 1 | 6 2 | 8 3 | 0 5 4 | 2 4 5 | 2 3 6 | 1 2 7 | 0 1 8 | 3 4 9 | 3 5 10 | 0 2 11 | -------------------------------------------------------------------------------- /src/main/resources/data/graph/tinyDG.txt: -------------------------------------------------------------------------------- 1 | 13 2 | 22 3 | 4 2 4 | 2 3 5 | 3 2 6 | 6 0 7 | 0 1 8 | 2 0 9 | 11 12 10 | 12 9 11 | 9 10 12 | 9 11 13 | 7 9 14 | 10 12 15 | 11 4 16 | 4 3 17 | 3 5 18 | 6 8 19 | 8 6 20 | 5 4 21 | 0 5 22 | 6 4 23 | 6 9 24 | 7 6 25 | -------------------------------------------------------------------------------- /src/main/resources/data/graph/tinyDG2.txt: -------------------------------------------------------------------------------- 1 | 6 2 | 8 3 | 5 0 4 | 2 4 5 | 3 2 6 | 1 2 7 | 0 1 8 | 4 3 9 | 3 5 10 | 0 2 11 | -------------------------------------------------------------------------------- /src/main/resources/data/graph/tinyEWG.txt: -------------------------------------------------------------------------------- 1 | 8 2 | 16 3 | 4 5 0.35 4 | 4 7 0.37 5 | 5 7 0.28 6 | 0 7 0.16 7 | 1 5 0.32 8 | 0 4 0.38 9 | 2 3 0.17 10 | 1 7 0.19 11 | 0 2 0.26 12 | 1 2 0.36 13 | 1 3 0.29 14 | 2 7 0.34 15 | 6 2 0.40 16 | 3 6 0.52 17 | 6 0 0.58 18 | 6 4 0.93 19 | -------------------------------------------------------------------------------- /src/main/resources/data/graph/tinyG.txt: -------------------------------------------------------------------------------- 1 | 13 2 | 13 3 | 0 5 4 | 4 3 5 | 0 1 6 | 9 12 7 | 6 4 8 | 5 4 9 | 0 2 10 | 11 12 11 | 9 10 12 | 0 6 13 | 7 8 14 | 9 11 15 | 5 3 16 | -------------------------------------------------------------------------------- /src/main/resources/image/stock_buy_sell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nibnait/algorithms/4d88870d479793b7bcf8418402251acb9498eec9/src/main/resources/image/stock_buy_sell.png -------------------------------------------------------------------------------- /src/main/resources/properties/default.properties: -------------------------------------------------------------------------------- 1 | APPID=nevermore.api -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/algorithm_practice/TempTest.java: -------------------------------------------------------------------------------- 1 | package algorithm_practice; 2 | 3 | import cc.tianbin.common.CommonConstants; 4 | import cc.tianbin.common.util.*; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | /** 9 | * Created by nibnait on 2020/11/24 10 | */ 11 | public class TempTest { 12 | 13 | @Test 14 | public void testCase() { 15 | for (int i = 0; i < CommonConstants.TEST_CASE_COUNT_1000; i++) { 16 | int[] arr = SysRandom.generateArr(); 17 | SysOut.printArray(arr); 18 | selectSort(arr); 19 | SysOut.printArray(arr); 20 | if (!CompareUtils.isSortAsc(arr)) { 21 | SysOut.println("。。。有问题❗️❗️❗️"); 22 | Assert.assertTrue(false); 23 | } 24 | 25 | SystemUtil.printLiteCuttingLine(); 26 | } 27 | } 28 | 29 | private void selectSort(int[] arr) { 30 | if (arr == null || arr.length == 0) { 31 | return; 32 | } 33 | 34 | for (int end = arr.length - 1; end > 0; end--) { 35 | int maxValueIndex = 0; 36 | for (int i = 1; i <= end; i++) { 37 | maxValueIndex = arr[maxValueIndex] > arr[i] ? maxValueIndex : i; 38 | } 39 | SwapUtil.swap(arr, maxValueIndex, end); 40 | } 41 | } 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/algorithm_practice/二分查找.java: -------------------------------------------------------------------------------- 1 | package algorithm_practice; 2 | 3 | import junit.framework.TestCase; 4 | import org.junit.Test; 5 | 6 | /** 7 | * Created by nibnait on 2019-08-23 8 | */ 9 | public class 二分查找 extends TestCase { 10 | 11 | @Test 12 | public void testM() { 13 | int[] a = {1, 3, 4, 5}; 14 | System.out.println(serch(a, 3)); 15 | System.out.println(serch(a, 1)); 16 | } 17 | 18 | public int serch(int[] a, int target) { 19 | int NOT_FOUND = -1; 20 | if (a == null || a.length < 1) { 21 | return NOT_FOUND; 22 | } 23 | int left = 0; 24 | int right = a.length - 1; 25 | while (left <= right) { 26 | int mid = (left + right + 1) / 2; 27 | if (a[mid] == target) { 28 | return mid; 29 | } else if (a[mid] < target) { 30 | left = mid + 1; 31 | } else { 32 | right = mid - 1; 33 | } 34 | } 35 | return NOT_FOUND; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/algorithm_practice/快速排序.java: -------------------------------------------------------------------------------- 1 | package algorithm_practice; 2 | 3 | import cc.tianbin.common.util.SysOut; 4 | import org.junit.Test; 5 | 6 | import static cc.tianbin.common.util.SwapUtil.swap; 7 | 8 | /** 9 | * Created by nibnait on 2020/11/23 10 | */ 11 | public class 快速排序 { 12 | @Test 13 | public void testCase() { 14 | 15 | // 73 为完全二叉树的根节点 16 | int[] nums = new int[]{73, 98, 27, 36, 77, 22, 6, 32, 83, 69}; 17 | SysOut.printArray(nums); 18 | 19 | quickSort(nums, 0, nums.length-1); 20 | SysOut.printArray(nums); 21 | 22 | } 23 | 24 | private void quickSort(int[] nums, int left, int right) { 25 | if (left >= right) { 26 | return; 27 | } 28 | 29 | int p = partition(nums, left, right); 30 | quickSort(nums, left, p-1); 31 | quickSort(nums, p+1, right); 32 | } 33 | 34 | 35 | private int partition(int[] nums, int left, int right) { 36 | 37 | int flag = left; 38 | for (int i = left; i <= right; i++) { 39 | // 降序 40 | if (nums[i] > nums[right]) { 41 | swap(nums, i, flag); 42 | flag++; 43 | } 44 | } 45 | swap(nums, right, flag); 46 | return flag; 47 | } 48 | 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/algorithmzuo/README.md: -------------------------------------------------------------------------------- 1 | # 跟着左神写算法 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/algorithmzuo/b_体系学习班/README.md: -------------------------------------------------------------------------------- 1 | # 体系学习班 2 | 3 | [课程目录](https://github.com/algorithmzuo/class-notes/blob/main/%E8%AF%BE%E5%A0%82%E5%86%85%E5%AE%B9%E6%B1%87%E6%80%BB/%E7%AE%97%E6%B3%95%E5%92%8C%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%BD%93%E7%B3%BB%E5%AD%A6%E4%B9%A0%E7%8F%AD) 4 | 5 | [代码](https://github.com/algorithmzuo/algorithmbasic2020) 6 | 7 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/algorithmzuo/b_体系学习班/c0103_异或运算/Code01_Swap.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithmzuo.b_体系学习班.c0103_异或运算; 2 | 3 | public class Code01_Swap { 4 | 5 | /** 6 | * 不用额外变量交换两个数的值 7 | */ 8 | public static void main(String[] args) { 9 | 10 | int a = 16; 11 | int b = 603; 12 | 13 | System.out.println(a); 14 | System.out.println(b); 15 | 16 | 17 | a = a ^ b; 18 | b = a ^ b; 19 | a = a ^ b; 20 | 21 | 22 | System.out.println(a); 23 | System.out.println(b); 24 | 25 | 26 | 27 | int[] arr = {3,1,100}; 28 | 29 | int i = 0; 30 | int j = 0; 31 | 32 | arr[i] = arr[i] ^ arr[j]; 33 | arr[j] = arr[i] ^ arr[j]; 34 | arr[i] = arr[i] ^ arr[j]; 35 | 36 | System.out.println(arr[i] + " , " + arr[j]); 37 | 38 | 39 | 40 | System.out.println(arr[0]); 41 | System.out.println(arr[2]); 42 | 43 | swap(arr, 0, 0); 44 | 45 | System.out.println(arr[0]); 46 | System.out.println(arr[2]); 47 | } 48 | 49 | 50 | public static void swap (int[] arr, int i, int j) { 51 | // arr[0] = arr[0] ^ arr[0]; 52 | arr[i] = arr[i] ^ arr[j]; 53 | arr[j] = arr[i] ^ arr[j]; 54 | arr[i] = arr[i] ^ arr[j]; 55 | } 56 | 57 | 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/algorithmzuo/b_体系学习班/c0105_栈和队列/Code04_RingArray.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithmzuo.b_体系学习班.c0105_栈和队列; 2 | 3 | /** 4 | * 用环形数组实现队列 5 | * Created by nibnait on 2022/07/06 6 | */ 7 | public class Code04_RingArray { 8 | 9 | public static class MyQueue { 10 | private final int[] arr; 11 | private final int limit; 12 | private int pollIndex; 13 | private int addIndex; 14 | private int size; 15 | 16 | public MyQueue(int limit) { 17 | arr = new int[limit]; 18 | pollIndex = 0; 19 | addIndex = 0; 20 | size = 0; 21 | this.limit = limit; 22 | } 23 | 24 | public void add(int value){ 25 | if (size == limit) { 26 | throw new RuntimeException("队列满了"); 27 | } 28 | size++; 29 | arr[addIndex] = value; 30 | addIndex = getNext(addIndex); 31 | } 32 | 33 | public int poll() { 34 | if (size == 0) { 35 | throw new RuntimeException("队列空了"); 36 | } 37 | size--; 38 | int ans = arr[pollIndex]; 39 | pollIndex = getNext(pollIndex); 40 | return ans; 41 | } 42 | 43 | private int getNext(int index){ 44 | return index < limit - 1 ? index + 1 : 0; 45 | } 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/algorithmzuo/b_体系学习班/c0105_栈和队列/Code05_GetMinStack.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithmzuo.b_体系学习班.c0105_栈和队列; 2 | 3 | /** 4 | * 实现有getMin功能的栈 5 | * Created by nibnait on 2022/07/06 6 | */ 7 | public class Code05_GetMinStack { 8 | 9 | /** 10 | * 两个栈 11 | * 一个正常的数据栈 12 | * 一个【最小值栈】。当有新的数 push 的时候, 13 | * 如果当前值 <【最小值栈】的栈顶, 14 | * 则【最小值栈】push 新的数 15 | * 否则【最小值栈】push 原来的栈顶 16 | */ 17 | } 18 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/algorithmzuo/b_体系学习班/c01xx_一些超级基础的算法.md: -------------------------------------------------------------------------------- 1 | ## 排序、二分查找、异或运算、栈和队列 2 | 3 | ### 用master公式来估计时间复杂度 4 | Master 公式: 5 | 形如 T(N) = a * T(N/b) + O(N^d) (a、b、d都是常数)的递归函数,可以直接通过 Master 公式来确定时间复杂度 6 | - 如果 log(b,a) < d, 复杂度为 O(N^d) 7 | - 如果 log(b,a) > d, 复杂度为 O(N^log(b,a)) 8 | - 如果 log(b,a) == d, 复杂度为 O(N^d * logN) 9 | 10 | ### 堆 和 加强堆 11 | [堆相关](../../../java/data_struct/ds1_堆) 12 | 13 | ### 排序算法总结 14 | 15 | | | 时间复杂度 | 额外空间复杂度 | 稳定性 | 16 | | -------- | ---------- | -------------- | ------ | 17 | | 选择排序 | O(N^2) | O(1) | 无 | 18 | | 冒泡排序 | O(N^2) | O(1) | 有 | 19 | | 插入排序 | O(N^2) | O(1) | 有 | 20 | | 归并排序 | O(NxlogN) | O(N) | 有 | 21 | | 随机快排 | O(NxlogN) | O(logN) | 无 | 22 | | 堆排序 | O(NxlogN) | O(1) | 无 | 23 | | === | === | === | === | 24 | | 计数排序 | O(N) | O(1) | 有 | 25 | | 基数排序 | O(N) | O(1) | 有 | 26 | 27 | 1)不基于比较的排序,对样本数据有严格要求,不易改写 28 | 2)基于比较的排序,只要规定好两个样本怎么比大小就可以直接复用 29 | 3)基于比较的排序,时间复杂度的极限是O(N*logN) 30 | 4)时间复杂度O(N*logN)、额外空间复杂度低于O(N)、且稳定的基于比较的 31 | 排序是不存在的。 32 | 5)为了绝对的速度选快排、为了省空间选堆排、为了稳定性选归并 33 | 34 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/algorithmzuo/b_体系学习班/c0203_树/Code05_EncodeNaryTreeToBinaryTree.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithmzuo.b_体系学习班.c0203_树; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * Created by nibnait on 2022/10/27 7 | */ 8 | public class Code05_EncodeNaryTreeToBinaryTree { 9 | 10 | @Test 11 | public void test() { 12 | 13 | } 14 | 15 | /** 16 | * N叉树如何通过二叉树来序列化、并完成反序列化 17 | * https://leetcode.com/problems/encode-n-ary-tree-to-binary-tree 18 | */ 19 | } 20 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/algorithmzuo/b_体系学习班/c0300_贪心/Code04_IPO.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithmzuo.b_体系学习班.c0300_贪心; 2 | 3 | import lombok.AllArgsConstructor; 4 | import org.junit.Assert; 5 | import org.junit.Test; 6 | 7 | /** 8 | * Created by nibnait on 2022/11/02 9 | */ 10 | public class Code04_IPO { 11 | 12 | @Test 13 | public void test() { 14 | int K = 3; 15 | int W = 3; 16 | int[] profits = new int[]{2,3,5,5,453}; 17 | int[] costs = new int[]{3,1,2,6,23}; 18 | int result = findMaximizedCapital(K, W, profits, costs); 19 | Assert.assertEquals(16, result); 20 | 21 | } 22 | 23 | /** 24 | * @param K 最多能做 K 个项目 25 | * @param W 启动资金 26 | * @param profits 每i个项目的利润 27 | * @param costs 第i个项目的花费 28 | * @return 最后获得的最大钱数 29 | */ 30 | private int findMaximizedCapital(int K, int W, int[] profits, int[] costs) { 31 | return 0; 32 | } 33 | 34 | @AllArgsConstructor 35 | private static class Project { 36 | public int profit; 37 | public int cost; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/algorithmzuo/b_体系学习班/c03xx_贪心算法.md: -------------------------------------------------------------------------------- 1 | ## 贪心 2 | 自然智慧 想出的局部最优解 -> 全局最优解 3 | 不断试错,没有证明。。 4 | 5 | - [Code01_Light](./c0300_贪心/Code01_Light.java) 6 | 给定一个字符串str,只由'X'和'.'两种字符构成 7 | 'X'表示墙,不能放灯,也不需要点亮;'.'表示居民点,可以放灯,需要点亮 8 | 如果灯放在i位置,可以让i-1,i和i+1三个位置被点亮 9 | 返回如果点亮str中所有需要点亮的位置,至少需要几盏灯 10 | 11 | - [Code02_LessMoneySplitGold](./c0300_贪心/Code02_LessMoneySplitGold.java) 12 | 一块金条切成两半,是需要花费和长度数值一样的铜板 13 | 比如长度为20的金条,不管怎么切都要花费20个铜板,一群人想整分整块金条,怎么分最省铜板? 14 | 例如,给定数组{10,20,30},代表一共三个人,整块金条长度为60,金条要分成10,20,30三个部分。 15 | 如果先把长度60的金条分成10和50,花费60;再把长度50的金条分成20和30,花费50;一共花费110铜板 16 | 但如果先把长度60的金条分成30和30,花费60;再把长度30金条分成10和20,花费30;一共花费90铜板 17 | 输入一个数组,返回分割的最小代价 18 | 19 | - [Code03_BestArrange](./c0300_贪心/Code03_BestArrange.java) 20 | 一些项目要占用一个会议室宣讲,会议室不能同时容纳两个项目的宣讲,给你每一个项目开始的时间和结束的时间 21 | 你来安排宣讲的日程,要求会议室进行的宣讲的场次最多,返回最多的宣讲场次 22 | 23 | - [Code04_IPO](./c0300_贪心/Code04_IPO.java) 24 | 输入正数数组costs、正数数组profits、正数K和正数M 25 | costs[i]表示i号项目的花费 26 | profits[i]表示i号项目在扣除花费之后还能挣到的钱(利润) 27 | K表示你只能串行的最多做k个项目 28 | M表示你初始的资金 29 | 说明:每做完一个项目,马上获得的收益,可以支持你去做下一个项目,不能并行的做项目。 30 | 输出:最后获得的最大钱数 31 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/algorithmzuo/b_体系学习班/c04xx_并查集.md: -------------------------------------------------------------------------------- 1 | ## 并查集 2 | [并查集 数据结构](../../../../../java/cc/tianbin/data_struct/ds3_并查集) 3 | 4 | 5 | 一群朋友中,有几个不相交的朋友圈 6 | Leetcode题目: 7 | 8 | 岛问题(递归解法 + 并查集解法 + 并行解法) 9 | 给定一个二维数组matrix,里面的值不是1就是0,上、下、左、右相邻的1认为是一片岛,返回matrix中岛的数量 10 | 11 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/algorithmzuo/b_体系学习班/c0500_图/Code01_BFS.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithmzuo.b_体系学习班.c0500_图; 2 | 3 | import cc.tianbin.data_struct.ds4_图.Node; 4 | import org.junit.Test; 5 | 6 | import java.util.*; 7 | 8 | /** 9 | * Created by nibnait on 2022/11/06 10 | */ 11 | public class Code01_BFS { 12 | 13 | @Test 14 | public void test() { 15 | 16 | } 17 | 18 | public List bfs(Node start) { 19 | List travelArr = new ArrayList<>(); 20 | if (start == null) { 21 | return travelArr; 22 | } 23 | 24 | Queue queue = new LinkedList(); 25 | Set set = new HashSet<>(); 26 | queue.add(start); 27 | set.add(start); 28 | while (!queue.isEmpty()) { 29 | Node cur = queue.poll(); 30 | travelArr.add(cur); 31 | 32 | for (Node next : cur.nexts) { 33 | if (!set.contains(next)) { 34 | break; 35 | } 36 | 37 | queue.add(next); 38 | set.add(next); 39 | } 40 | } 41 | 42 | return travelArr; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/algorithmzuo/b_体系学习班/c0500_图/Code02_DFS.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithmzuo.b_体系学习班.c0500_图; 2 | 3 | import cc.tianbin.data_struct.ds4_图.Node; 4 | import org.junit.Test; 5 | 6 | import java.util.*; 7 | 8 | /** 9 | * Created by nibnait on 2022/11/06 10 | */ 11 | public class Code02_DFS { 12 | 13 | @Test 14 | public void test() { 15 | 16 | } 17 | 18 | public List dfs(Node start) { 19 | List travelArr = new ArrayList<>(); 20 | if (start == null) { 21 | return travelArr; 22 | } 23 | 24 | Stack stack = new Stack(); 25 | Set set = new HashSet<>(); 26 | stack.push(start); 27 | set.add(start); 28 | travelArr.add(start); 29 | while (!stack.isEmpty()) { 30 | Node cur = stack.pop(); 31 | for (Node next : cur.nexts) { 32 | if (set.contains(next)) { 33 | break; 34 | } 35 | 36 | stack.push(cur); 37 | stack.push(next); 38 | set.add(next); 39 | travelArr.add(next); 40 | } 41 | } 42 | 43 | return travelArr; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/algorithmzuo/b_体系学习班/c0500_图/Code03_1_TopologySort.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithmzuo.b_体系学习班.c0500_图; 2 | 3 | import cc.tianbin.data_struct.ds4_图.Graph; 4 | import cc.tianbin.data_struct.ds4_图.Node; 5 | 6 | import java.util.*; 7 | 8 | /** 9 | * Created by nibnait on 2022/11/06 10 | */ 11 | public class Code03_1_TopologySort { 12 | 13 | /** 14 | * 有向无环图 15 | */ 16 | public List topSort(Graph graph) { 17 | 18 | // 每个节点的剩余入度 19 | Map inDegreeMap = new HashMap<>(); 20 | // 没有入度的节点 21 | Queue zeroInDegreeQueue = new LinkedList<>(); 22 | 23 | for (Node node : graph.nodes.values()) { 24 | inDegreeMap.put(node, node.in); 25 | if (node.in == 0) { 26 | zeroInDegreeQueue.add(node); 27 | } 28 | } 29 | 30 | List result = new ArrayList<>(); 31 | while (!zeroInDegreeQueue.isEmpty()) { 32 | Node cur = zeroInDegreeQueue.poll(); 33 | result.add(cur); 34 | for (Node next : cur.nexts) { 35 | inDegreeMap.put(next, inDegreeMap.get(next) - 1); 36 | if (inDegreeMap.get(next) == 0) { 37 | zeroInDegreeQueue.add(next); 38 | } 39 | } 40 | } 41 | 42 | return result; 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/algorithmzuo/b_体系学习班/c0600_常见的递归.md: -------------------------------------------------------------------------------- 1 | ## 常见的递归 2 | 3 | 打印n层汉诺塔从最左边移动到最右边的全部过程(递归+非递归实现) 4 | [Code01_Hanoi](./c0600_常见的递归/Code01_Hanoi.java) 5 | 6 | 打印一个字符串的全部子序列 7 | 打印一个字符串的全部子序列,要求不要出现重复字面值的子序列 8 | [Code02_PrintAllSubSequences](./c0600_常见的递归/Code02_PrintAllSubSequences.java) 9 | 10 | 打印一个字符串的全部排列 11 | 打印一个字符串的全部排列,要求不要出现重复的排列 12 | [Code03_PrintAllPermutations](./c0600_常见的递归/Code03_PrintAllPermutations.java) 13 | 14 | 给定一个栈,请逆序这个栈,不能申请额外的数据结构,只能使用递归函数 15 | [Code04_ReverseStackUsingRecursive](./c0600_常见的递归/Code04_ReverseStackUsingRecursive.java) 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/algorithmzuo/b_体系学习班/c0600_常见的递归/Code04_ReverseStackUsingRecursive.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.algorithmzuo.b_体系学习班.c0600_常见的递归; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Stack; 6 | 7 | /** 8 | * Created by nibnait on 2022/11/08 9 | */ 10 | public class Code04_ReverseStackUsingRecursive { 11 | 12 | @Test 13 | public void test() { 14 | Stack stack = new Stack(); 15 | stack.push(1); 16 | stack.push(2); 17 | stack.push(3); 18 | stack.push(4); 19 | stack.push(5); 20 | reverse(stack); 21 | while (!stack.isEmpty()) { 22 | System.out.println(stack.pop()); 23 | } 24 | 25 | } 26 | 27 | /** 28 | * 使用递归,将栈逆序 29 | */ 30 | public void reverse(Stack stack) { 31 | if (stack == null || stack.isEmpty()) { 32 | return; 33 | } 34 | 35 | int last = process(stack); 36 | reverse(stack); 37 | // 把每次的栈底 push 进来 38 | stack.push(last); 39 | } 40 | 41 | /** 42 | * 每次都返回当前的栈底 43 | */ 44 | private int process(Stack stack) { 45 | Integer result = stack.pop(); 46 | if (stack.isEmpty()) { 47 | return result; 48 | } 49 | 50 | int last = process(stack); 51 | stack.push(result); 52 | return last; 53 | } 54 | 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/algorithmzuo/c_大厂刷题班/README.md: -------------------------------------------------------------------------------- 1 | # 刷题班 2 | 3 | [课程目录](https://github.com/algorithmzuo/class-notes/blob/main/%E8%AF%BE%E5%A0%82%E5%86%85%E5%AE%B9%E6%B1%87%E6%80%BB/%E5%A4%A7%E5%8E%82%E7%AE%97%E6%B3%95%E5%92%8C%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E5%88%B7%E9%A2%98%E7%8F%AD) 4 | 5 | [代码](https://github.com/algorithmzuo/coding-for-great-offer) 6 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/common/util/DateTimeUtilTest.java: -------------------------------------------------------------------------------- 1 | package common.util; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Date; 6 | 7 | /** 8 | * Created by nibnait on 2021/04/07 9 | */ 10 | public class DateTimeUtilTest { 11 | @Test 12 | public void test01() { 13 | Date date = new Date(); 14 | System.out.println(date.getTime()); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/common/util/ExcelReadUtilsTest.java: -------------------------------------------------------------------------------- 1 | package common.util; 2 | 3 | import org.junit.Test; 4 | 5 | import java.io.IOException; 6 | 7 | /** 8 | * Created by nibnait on 2021/03/26 9 | */ 10 | public class ExcelReadUtilsTest { 11 | 12 | @Test 13 | public void read() throws IOException { 14 | 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/common/util/validate/FluentValidatorTest.java: -------------------------------------------------------------------------------- 1 | package common.util.validate; 2 | 3 | /** 4 | * Created by nibnait on 2021/08/22 5 | */ 6 | public class FluentValidatorTest { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/demo/Main.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo; 2 | 3 | /** 4 | * Created by nibnait on 2020-01-08 5 | */ 6 | public class Main { 7 | 8 | 9 | } -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/demo/java/ObjectTest.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java; 2 | 3 | //import org.junit.Test; 4 | 5 | /** 6 | * Created by nibnait on 2021/04/01 7 | */ 8 | public class ObjectTest { 9 | 10 | // @Test 11 | // public void testEquals() { 12 | // Byte saleType = null; 13 | // Byte saleType1 = 1; 14 | // 15 | // boolean equals = saleType1.equals(saleType); 16 | // System.out.println(equals); 17 | // 18 | // } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/demo/java/OptionalTest.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Optional; 6 | 7 | /** 8 | * Created by nibnait on 2022/03/17 9 | */ 10 | public class OptionalTest { 11 | 12 | @Test 13 | public void test01() { 14 | Integer i = null; 15 | System.out.println(Optional.ofNullable(i).orElse(null)); 16 | 17 | i = 1; 18 | System.out.println(Optional.ofNullable(i).orElse(null)); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/demo/java/SwitchCaseTest.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * Created by nibnait on 2021/07/13 7 | */ 8 | public class SwitchCaseTest { 9 | 10 | @Test 11 | public void test01() { 12 | 13 | // Integer i = 1; 14 | Integer i = null; 15 | 16 | switch (i) { 17 | case 1: 18 | System.out.println("1:" + i); 19 | // break; 20 | case 2: 21 | System.out.println("2:" + i); 22 | // break; 23 | default: 24 | System.out.println("default:" + i); 25 | } 26 | 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/demo/java/spring/SpringTest.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.java.spring; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * Created by nibnait on 2022/09/30 7 | */ 8 | public class SpringTest { 9 | 10 | @Test 11 | public void test01() { 12 | 13 | 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/demo/java/反射/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nibnait/algorithms/4d88870d479793b7bcf8418402251acb9498eec9/src/main/test/cc/tianbin/demo/java/反射/README.md -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/demo/temp/JsonParseTest.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.demo.temp; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.alibaba.fastjson.JSONObject; 5 | import org.apache.commons.lang3.StringUtils; 6 | import org.junit.Test; 7 | 8 | /** 9 | * Created by nibnait on 2020-02-25 10 | */ 11 | public class JsonParseTest { 12 | 13 | @Test 14 | public void test() { 15 | String s = JSON.toJSONString(null); 16 | System.out.println(s); 17 | } 18 | 19 | @Test 20 | public void testCase() { 21 | 22 | String attribute_json = "{\"active_at\":1582566155,\"user_name\":\"32a9bd7c2\"}"; 23 | JSONObject jsonObject = JSONObject.parseObject(attribute_json); 24 | System.out.println(jsonObject); 25 | String is_from_tp_new_retail = jsonObject.getString("is_from_tp_new_retail"); 26 | System.out.println(is_from_tp_new_retail); 27 | 28 | if (StringUtils.isNotBlank(attribute_json) && jsonObject.getString("is_from_tp_new_retail") == "1") { 29 | System.out.println("asdfsafsafsa"); 30 | } 31 | } 32 | 33 | 34 | } -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/java/lang/test/String.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nibnait/algorithms/4d88870d479793b7bcf8418402251acb9498eec9/src/main/test/cc/tianbin/java/lang/test/String.class -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/java/lang/test/String_.java: -------------------------------------------------------------------------------- 1 | package java.lang.test; 2 | 3 | /** 4 | * Created by nibnait on 2020/11/11 5 | */ 6 | public class String_ { 7 | 8 | public void test() { 9 | System.out.println("自定义String 加载成功"); 10 | } 11 | 12 | 13 | public static void main(String[] args) { 14 | System.out.println("我是自定义的String"); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/java/mybatis/MybatisTest.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.java.mybatis; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * Created by nibnait on 2022/10/18 7 | */ 8 | public class MybatisTest { 9 | 10 | @Test 11 | public void test() { 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/javalang/test/FinallyTest.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.javalang.test; 2 | 3 | import io.github.nibnait.common.exception.ClientViewException; 4 | import org.junit.Test; 5 | 6 | /** 7 | * Created by nibnait on 2022/05/11 8 | */ 9 | public class FinallyTest { 10 | 11 | @Test 12 | public void test01() { 13 | try { 14 | System.out.println("try"); 15 | throw new RuntimeException("123"); 16 | } catch (Exception e) { 17 | System.out.println("catch"); 18 | return; 19 | } finally { 20 | System.out.println("finally"); 21 | } 22 | } 23 | 24 | @Test 25 | public void test02() { 26 | try { 27 | System.out.println("try"); 28 | return; 29 | } catch (Exception e) { 30 | System.out.println("catch"); 31 | } finally { 32 | System.out.println("finally"); 33 | } 34 | } 35 | 36 | @Test 37 | public void test03() { 38 | try { 39 | throw new ClientViewException("123"); 40 | } finally { 41 | System.out.println(111); 42 | } 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/test/cc/tianbin/tmp/interview/Main.java: -------------------------------------------------------------------------------- 1 | package cc.tianbin.tmp.interview; 2 | 3 | public class Main { 4 | 5 | public static void main(String[] args) { 6 | } 7 | 8 | } --------------------------------------------------------------------------------