├── .gitignore └── sandbox ├── pom.xml └── src └── main ├── java ├── com │ └── cipher │ │ ├── algorithm_visualization │ │ ├── A_Base │ │ │ ├── AlgoFrame.java │ │ │ ├── AlgoVisHelper.java │ │ │ └── AlgoVisualizer.java │ │ ├── B_Circle │ │ │ ├── Circle.java │ │ │ ├── CircleFrame.java │ │ │ └── CircleVisualizer.java │ │ ├── C_Money │ │ │ ├── MoneyFrame.java │ │ │ └── MoneyVisualizer.java │ │ ├── D_Montecarlo │ │ │ ├── montyhall │ │ │ │ └── ThreeGatesExperiment.java │ │ │ ├── openbox │ │ │ │ └── WinningPrice.java │ │ │ └── pi │ │ │ │ ├── Circle.java │ │ │ │ ├── MonteCarloExperiment.java │ │ │ │ ├── MonteCarloPiData.java │ │ │ │ ├── PiFrame.java │ │ │ │ └── PiVisualizer.java │ │ ├── E_Sort │ │ │ ├── heap │ │ │ │ ├── HeapSortData.java │ │ │ │ ├── HeapSortFrame.java │ │ │ │ └── HeapSortVisualizer.java │ │ │ ├── insertion │ │ │ │ ├── InsertionSortData.java │ │ │ │ ├── InsertionSortFrame.java │ │ │ │ └── InsertionSortVisualizer.java │ │ │ ├── merge │ │ │ │ ├── MergeSortData.java │ │ │ │ ├── MergeSortFrame.java │ │ │ │ ├── MergeSortTest.java │ │ │ │ ├── MergeSortVisualizer.java │ │ │ │ └── MergeSortVisualizerNoRecursive.java │ │ │ ├── quick │ │ │ │ ├── simple │ │ │ │ │ ├── QuickSortDataSimple.java │ │ │ │ │ ├── QuickSortFrameSimple.java │ │ │ │ │ └── QuickSortVisualizerSimple.java │ │ │ │ ├── three_ways │ │ │ │ │ ├── QuickSortData3Way.java │ │ │ │ │ ├── QuickSortFrame3Way.java │ │ │ │ │ └── QuickSortVisualizer3Way.java │ │ │ │ ├── two_ways │ │ │ │ │ ├── QuickSortData2Way.java │ │ │ │ │ ├── QuickSortFrame2Way.java │ │ │ │ │ └── QuickSortVisualizer2Way.java │ │ │ │ └── with_random_pivot │ │ │ │ │ ├── QuickSortDataRandom.java │ │ │ │ │ ├── QuickSortFrameRandom.java │ │ │ │ │ └── QuickSortVisualizerRandom.java │ │ │ └── selection │ │ │ │ ├── SelectionSortData.java │ │ │ │ ├── SelectionSortFrame.java │ │ │ │ └── SelectionSortVisualizer.java │ │ ├── F_Maze │ │ │ ├── MazeData.java │ │ │ ├── MazeFrame.java │ │ │ ├── bfs │ │ │ │ └── MazeVisualizer.java │ │ │ ├── dfs │ │ │ │ ├── MazeVisualizer.java │ │ │ │ └── MazeVisualizerNoRecursive.java │ │ │ └── maze_101_101.txt │ │ ├── G_Build_Maze │ │ │ ├── MazeData.java │ │ │ ├── MazeFrame.java │ │ │ ├── bfs │ │ │ │ └── MazeVisualizer.java │ │ │ ├── dfs │ │ │ │ ├── MazeVisualizer.java │ │ │ │ └── MazeVisualizerNoRecursive.java │ │ │ ├── random_1 │ │ │ │ ├── MazeVisualizer.java │ │ │ │ └── RandomQueue.java │ │ │ └── random_2 │ │ │ │ ├── MazeVisualizer.java │ │ │ │ └── RandomQueue2.java │ │ ├── H_Mine_Sweeper │ │ │ ├── MineSweeperData.java │ │ │ ├── MineSweeperFrame.java │ │ │ ├── MineSweeperVisualizer.java │ │ │ ├── ShuffleExp.java │ │ │ └── images │ │ │ │ ├── 0.png │ │ │ │ ├── 1.png │ │ │ │ ├── 2.png │ │ │ │ ├── 3.png │ │ │ │ ├── 4.png │ │ │ │ ├── 5.png │ │ │ │ ├── 6.png │ │ │ │ ├── 7.png │ │ │ │ ├── 8.png │ │ │ │ ├── block.png │ │ │ │ ├── flag.png │ │ │ │ └── mine.png │ │ ├── I_Move_Box │ │ │ ├── Board.java │ │ │ ├── GameData.java │ │ │ ├── GameFrame.java │ │ │ ├── GameVisualizer.java │ │ │ └── level │ │ │ │ ├── boston_08.txt │ │ │ │ ├── boston_09.txt │ │ │ │ ├── boston_16.txt │ │ │ │ ├── newyork_04.txt │ │ │ │ ├── newyork_05.txt │ │ │ │ └── newyork_06.txt │ │ ├── J_Fractal_Drawing │ │ │ ├── recursive_circle │ │ │ │ ├── CircleData.java │ │ │ │ ├── CircleFrame.java │ │ │ │ └── CircleVisualizer.java │ │ │ ├── sierpinski_carpet │ │ │ │ ├── CarpetData.java │ │ │ │ ├── CarpetFrame.java │ │ │ │ └── CarpetVisualizer.java │ │ │ ├── sierpinski_triangle │ │ │ │ ├── TriangleData.java │ │ │ │ ├── TriangleFrame.java │ │ │ │ └── TriangleVisualizer.java │ │ │ ├── snowflake_fractal │ │ │ │ ├── SnowflakeData.java │ │ │ │ ├── SnowflakeFrame.java │ │ │ │ └── SnowflakeVisualizer.java │ │ │ ├── tree_fractal │ │ │ │ ├── TreeData.java │ │ │ │ ├── TreeFrame.java │ │ │ │ └── TreeVisualizer.java │ │ │ └── vicsek_fractal │ │ │ │ ├── VicsekData.java │ │ │ │ ├── VicsekFrame.java │ │ │ │ ├── VicsekFrame2.java │ │ │ │ └── VicsekVisualizer.java │ │ └── readme.md │ │ ├── algorithms │ │ ├── A_Sort │ │ │ ├── A_BubbleSort │ │ │ │ └── BubbleSort.java │ │ │ ├── B_SelectionSort │ │ │ │ └── SelectionSort.java │ │ │ ├── C_InsertionSort │ │ │ │ └── InsertionSort.java │ │ │ ├── D_ShellSort │ │ │ │ └── ShellSort.java │ │ │ ├── E_MergeSort │ │ │ │ └── MergeSort.java │ │ │ ├── F_QuickSort │ │ │ │ ├── QuickSort2Way.java │ │ │ │ ├── QuickSort3Way.java │ │ │ │ ├── QuickSortRandom.java │ │ │ │ └── QuickSortSimple.java │ │ │ ├── SortTestHelper.java │ │ │ ├── TestSort.java │ │ │ └── readme.md │ │ └── readme.md │ │ ├── checker │ │ ├── Check.java │ │ ├── Checker.java │ │ ├── ReflectionUtil.java │ │ └── readme.md │ │ ├── data_structure │ │ ├── A_Arrays │ │ │ ├── Array.java │ │ │ └── Main.java │ │ ├── B_Stacks_and_Queues │ │ │ ├── queue │ │ │ │ ├── ArrayQueue.java │ │ │ │ ├── LoopQueue.java │ │ │ │ ├── Queue.java │ │ │ │ └── TestQueue.java │ │ │ └── stack │ │ │ │ ├── ArrayStack.java │ │ │ │ ├── Stack.java │ │ │ │ └── ValidParentheses.java │ │ ├── C_Linked_List │ │ │ ├── LinkedList.java │ │ │ ├── LinkedListQueue.java │ │ │ ├── LinkedListStack.java │ │ │ └── Main.java │ │ ├── D_ListNode_and_Recursion │ │ │ ├── LeetCode203.java │ │ │ ├── LeetCode203_2.java │ │ │ ├── LeetCode203_3.java │ │ │ ├── LeetCode203_4.java │ │ │ ├── ListNode.java │ │ │ └── Sum.java │ │ ├── E_Binary_Search_Tree │ │ │ └── BST.java │ │ ├── F_Set_and_Map │ │ │ ├── FileOperation.java │ │ │ ├── map │ │ │ │ ├── BSTMap.java │ │ │ │ ├── LeetCode349.java │ │ │ │ ├── LeetCode350.java │ │ │ │ ├── LinkedListMap.java │ │ │ │ ├── Main.java │ │ │ │ └── Map.java │ │ │ ├── resource │ │ │ │ ├── a-tale-of-two-cities.txt │ │ │ │ └── pride-and-prejudice.txt │ │ │ └── set │ │ │ │ ├── BSTSet.java │ │ │ │ ├── LeetCode804.java │ │ │ │ ├── LinkedListSet.java │ │ │ │ ├── Main.java │ │ │ │ └── Set.java │ │ ├── G_Heap_and_Priority_Queue │ │ │ ├── LeetCode347.java │ │ │ ├── Main.java │ │ │ ├── MaxHeap.java │ │ │ └── PriorityQueue.java │ │ └── readme.md │ │ ├── handler_demo │ │ ├── handler │ │ │ ├── AbstractHandler.java │ │ │ ├── HandlerContext.java │ │ │ ├── HandlerProcessor.java │ │ │ ├── HandlerType.java │ │ │ └── biz │ │ │ │ ├── GroupHandler.java │ │ │ │ ├── NormalHandler.java │ │ │ │ └── PromotionHandler.java │ │ ├── model │ │ │ └── OrderDTO.java │ │ ├── service │ │ │ ├── IOrderService.java │ │ │ └── impl │ │ │ │ ├── OrderServiceImpl.java │ │ │ │ └── OrderServiceV2Impl.java │ │ └── util │ │ │ ├── BeanTool.java │ │ │ └── ClassScaner.java │ │ ├── interview │ │ ├── annotation │ │ │ ├── Aspect.java │ │ │ ├── IAspect.java │ │ │ ├── IOrder.java │ │ │ ├── ObjectFactory.java │ │ │ ├── Order.java │ │ │ └── TimeUsageAspect.java │ │ ├── buffer │ │ │ ├── BufferExampleTest.java │ │ │ └── WordCountTest.java │ │ ├── collection │ │ │ └── RandomStringGenerator.java │ │ ├── proxy │ │ │ ├── Aspect.java │ │ │ ├── IOrder.java │ │ │ ├── Order.java │ │ │ ├── ProxyExampleTest.java │ │ │ └── TimeUsageAspect.java │ │ └── stream │ │ │ └── Event.java │ │ ├── javassist │ │ ├── Example.java │ │ └── Person.java │ │ ├── jmh │ │ └── Test.java │ │ ├── jvm │ │ ├── FinalizeEscapeGC.java │ │ ├── HeapOOM.java │ │ ├── Hello.java │ │ ├── JHSDB_TestCase.java │ │ ├── JavaVMStackOOM.java │ │ ├── JavaVMStackSOF.java │ │ └── readme.md │ │ ├── method_name │ │ ├── FnConverter.java │ │ └── Foo.java │ │ ├── netty │ │ ├── client │ │ │ ├── ClientHandler.java │ │ │ └── NettyClient.java │ │ ├── constant │ │ │ ├── Command.java │ │ │ └── SerializerAlgorithm.java │ │ ├── core │ │ │ └── PacketCodec.java │ │ ├── protocol │ │ │ ├── Packet.java │ │ │ ├── request │ │ │ │ └── LoginRequestPacket.java │ │ │ └── response │ │ │ │ └── LoginResponsePacket.java │ │ ├── serialize │ │ │ ├── Serializer.java │ │ │ └── impl │ │ │ │ └── JSONSerializer.java │ │ └── server │ │ │ ├── NettyServer.java │ │ │ └── ServerHandler.java │ │ ├── pattern │ │ ├── adapter │ │ │ ├── GBTwoSocket.java │ │ │ ├── NoteBook.java │ │ │ ├── ThreePlugIf.java │ │ │ ├── TwoToThreeAdapter.java │ │ │ ├── TwoToThreeAdapterExtends.java │ │ │ └── readme.md │ │ ├── chain │ │ │ ├── CEO.java │ │ │ ├── Client.java │ │ │ ├── Custom.java │ │ │ ├── Director.java │ │ │ ├── Lead.java │ │ │ ├── Manager.java │ │ │ ├── PriceHandler.java │ │ │ ├── PriceHandlerFactory.java │ │ │ ├── Sales.java │ │ │ ├── VicePresident.java │ │ │ └── readme.md │ │ ├── factory │ │ │ ├── abs │ │ │ │ ├── Customer.java │ │ │ │ ├── factory │ │ │ │ │ ├── FactoryBMW.java │ │ │ │ │ ├── FactoryBMW320.java │ │ │ │ │ └── FactoryBMW523.java │ │ │ │ ├── product │ │ │ │ │ ├── Aircondition.java │ │ │ │ │ ├── AirconditionA.java │ │ │ │ │ ├── AirconditionB.java │ │ │ │ │ ├── Engine.java │ │ │ │ │ ├── EngineA.java │ │ │ │ │ └── EngineB.java │ │ │ │ └── readme.md │ │ │ ├── method │ │ │ │ ├── Customer.java │ │ │ │ ├── factory │ │ │ │ │ ├── FactoryBMW.java │ │ │ │ │ ├── FactoryBMW320.java │ │ │ │ │ └── FactoryBMW523.java │ │ │ │ ├── product │ │ │ │ │ ├── BMW.java │ │ │ │ │ ├── BMW320.java │ │ │ │ │ └── BMW523.java │ │ │ │ └── readme.md │ │ │ ├── readme.md │ │ │ └── simple │ │ │ │ ├── Customer.java │ │ │ │ ├── factory │ │ │ │ └── Factory.java │ │ │ │ ├── product │ │ │ │ ├── BMW.java │ │ │ │ ├── BMW320.java │ │ │ │ └── BMW523.java │ │ │ │ └── readme.md │ │ ├── observer │ │ │ ├── custom │ │ │ │ ├── Client.java │ │ │ │ ├── ConcreteObserver.java │ │ │ │ ├── Observer.java │ │ │ │ ├── Subject.java │ │ │ │ ├── WeatherStationSubject.java │ │ │ │ └── readme.md │ │ │ ├── jdk │ │ │ │ ├── Client.java │ │ │ │ ├── ConcreteObserver.java │ │ │ │ ├── WeatherStationSubject.java │ │ │ │ └── readme.md │ │ │ ├── readme.md │ │ │ └── special │ │ │ │ ├── Client.java │ │ │ │ ├── ConcreteObserver.java │ │ │ │ ├── Observer.java │ │ │ │ ├── Subject.java │ │ │ │ ├── WeatherStationSubject.java │ │ │ │ └── readme.md │ │ ├── proxy │ │ │ ├── Car.java │ │ │ ├── Moveable.java │ │ │ ├── dynamic │ │ │ │ ├── cglib │ │ │ │ │ ├── CarLogProxy.java │ │ │ │ │ ├── CarTimeProxy.java │ │ │ │ │ ├── Client.java │ │ │ │ │ ├── Train.java │ │ │ │ │ └── readme.md │ │ │ │ ├── custom │ │ │ │ │ ├── Client.java │ │ │ │ │ ├── InvocationHandler.java │ │ │ │ │ ├── Proxy.java │ │ │ │ │ ├── TimeHandler.java │ │ │ │ │ └── readme.md │ │ │ │ ├── jdk │ │ │ │ │ ├── Client.java │ │ │ │ │ ├── LogHandler.java │ │ │ │ │ ├── TimeHandler.java │ │ │ │ │ └── readme.md │ │ │ │ └── readme.md │ │ │ ├── readme.md │ │ │ └── statics │ │ │ │ ├── CarByExtend.java │ │ │ │ ├── CarLogProxy.java │ │ │ │ ├── CarTimeProxy.java │ │ │ │ ├── Client.java │ │ │ │ └── readme.md │ │ ├── readme.md │ │ ├── singleton │ │ │ ├── HungrySingleton.java │ │ │ ├── LazySingleton.java │ │ │ ├── Test.java │ │ │ └── readme.md │ │ ├── strategy │ │ │ ├── Client.java │ │ │ ├── Duck.java │ │ │ ├── FlyingStrategy.java │ │ │ ├── MallardDuck.java │ │ │ ├── RedheadDuck.java │ │ │ ├── RubberDuck.java │ │ │ ├── SpaceDuck.java │ │ │ ├── impl │ │ │ │ ├── FlyNoWay.java │ │ │ │ ├── FlyWithRocket.java │ │ │ │ └── FlyWithWing.java │ │ │ └── readme.md │ │ └── template │ │ │ ├── Coffee.java │ │ │ ├── Main.java │ │ │ ├── RefreshBeverage.java │ │ │ ├── Tea.java │ │ │ └── readme.md │ │ ├── redis_algorithm │ │ ├── readme.md │ │ └── skiplist │ │ │ ├── Constant.java │ │ │ ├── Test.java │ │ │ ├── Zskiplist.java │ │ │ ├── ZskiplistNode.java │ │ │ └── ZskiplistOp.java │ │ ├── spi │ │ ├── ChineseDemoServiceImpl.java │ │ ├── DemoService.java │ │ ├── EnglishDemoServiceImpl.java │ │ └── Main.java │ │ ├── test │ │ ├── NonReentrantLock.java │ │ ├── Solution.java │ │ └── Test.java │ │ └── threading │ │ ├── Communication.java │ │ ├── DelayExecutor.java │ │ ├── MyRunnable.java │ │ ├── NamedThreadFactory.java │ │ └── readme.md └── edu │ └── princeton │ └── cs │ └── algs4 │ ├── AVLTreeST.java │ ├── Accumulator.java │ ├── AcyclicLP.java │ ├── AcyclicSP.java │ ├── AdjMatrixEdgeWeightedDigraph.java │ ├── Alphabet.java │ ├── Arbitrage.java │ ├── AssignmentProblem.java │ ├── Average.java │ ├── BST.java │ ├── BTree.java │ ├── Bag.java │ ├── BellmanFordSP.java │ ├── BinaryDump.java │ ├── BinaryIn.java │ ├── BinaryInsertion.java │ ├── BinaryOut.java │ ├── BinarySearch.java │ ├── BinarySearchST.java │ ├── BinaryStdIn.java │ ├── BinaryStdOut.java │ ├── BinomialMinPQ.java │ ├── Bipartite.java │ ├── BipartiteMatching.java │ ├── BipartiteX.java │ ├── BlackFilter.java │ ├── BoruvkaMST.java │ ├── BoyerMoore.java │ ├── BreadthFirstDirectedPaths.java │ ├── BreadthFirstPaths.java │ ├── CC.java │ ├── CPM.java │ ├── Cat.java │ ├── ClosestPair.java │ ├── CollisionSystem.java │ ├── Complex.java │ ├── Count.java │ ├── Counter.java │ ├── Cycle.java │ ├── Date.java │ ├── DeDup.java │ ├── DegreesOfSeparation.java │ ├── DepthFirstDirectedPaths.java │ ├── DepthFirstOrder.java │ ├── DepthFirstPaths.java │ ├── DepthFirstSearch.java │ ├── Digraph.java │ ├── DigraphGenerator.java │ ├── DijkstraAllPairsSP.java │ ├── DijkstraSP.java │ ├── DijkstraUndirectedSP.java │ ├── DirectedCycle.java │ ├── DirectedCycleX.java │ ├── DirectedDFS.java │ ├── DirectedEdge.java │ ├── DirectedEulerianCycle.java │ ├── DirectedEulerianPath.java │ ├── DoublingRatio.java │ ├── DoublingTest.java │ ├── Draw.java │ ├── DrawListener.java │ ├── Edge.java │ ├── EdgeWeightedDigraph.java │ ├── EdgeWeightedDirectedCycle.java │ ├── EdgeWeightedGraph.java │ ├── EulerianCycle.java │ ├── EulerianPath.java │ ├── FFT.java │ ├── FarthestPair.java │ ├── FenwickTree.java │ ├── FibonacciMinPQ.java │ ├── FileIndex.java │ ├── FlowEdge.java │ ├── FlowNetwork.java │ ├── FloydWarshall.java │ ├── FordFulkerson.java │ ├── FrequencyCounter.java │ ├── GREP.java │ ├── GabowSCC.java │ ├── GaussJordanElimination.java │ ├── GaussianElimination.java │ ├── Genome.java │ ├── GlobalMincut.java │ ├── GrahamScan.java │ ├── Graph.java │ ├── GraphGenerator.java │ ├── Heap.java │ ├── HexDump.java │ ├── HopcroftKarp.java │ ├── Huffman.java │ ├── In.java │ ├── IndexBinomialMinPQ.java │ ├── IndexFibonacciMinPQ.java │ ├── IndexMaxPQ.java │ ├── IndexMinPQ.java │ ├── IndexMultiwayMinPQ.java │ ├── Insertion.java │ ├── InsertionX.java │ ├── Interval1D.java │ ├── Interval2D.java │ ├── Inversions.java │ ├── KMP.java │ ├── KWIK.java │ ├── Knuth.java │ ├── KosarajuSharirSCC.java │ ├── KruskalMST.java │ ├── LSD.java │ ├── LZW.java │ ├── LazyPrimMST.java │ ├── LinearProbingHashST.java │ ├── LinearProgramming.java │ ├── LinearRegression.java │ ├── LinkedBag.java │ ├── LinkedQueue.java │ ├── LinkedStack.java │ ├── LongestCommonSubstring.java │ ├── LongestRepeatedSubstring.java │ ├── LookupCSV.java │ ├── LookupIndex.java │ ├── MSD.java │ ├── MaxPQ.java │ ├── Merge.java │ ├── MergeBU.java │ ├── MergeX.java │ ├── MinPQ.java │ ├── Multiway.java │ ├── MultiwayMinPQ.java │ ├── NFA.java │ ├── NonrecursiveDFS.java │ ├── NonrecursiveDirectedDFS.java │ ├── Out.java │ ├── Particle.java │ ├── PatriciaSET.java │ ├── PatriciaST.java │ ├── Picture.java │ ├── PictureDump.java │ ├── Point2D.java │ ├── PrimMST.java │ ├── Queue.java │ ├── Quick.java │ ├── Quick3string.java │ ├── Quick3way.java │ ├── QuickFindUF.java │ ├── QuickUnionUF.java │ ├── QuickX.java │ ├── RabinKarp.java │ ├── RandomSeq.java │ ├── RectHV.java │ ├── RedBlackBST.java │ ├── ResizingArrayBag.java │ ├── ResizingArrayQueue.java │ ├── ResizingArrayStack.java │ ├── RunLength.java │ ├── SET.java │ ├── ST.java │ ├── SegmentTree.java │ ├── Selection.java │ ├── SeparateChainingHashST.java │ ├── SequentialSearchST.java │ ├── Shell.java │ ├── SparseVector.java │ ├── Stack.java │ ├── StaticSETofInts.java │ ├── StdArrayIO.java │ ├── StdAudio.java │ ├── StdDraw.java │ ├── StdIn.java │ ├── StdOut.java │ ├── StdRandom.java │ ├── StdStats.java │ ├── Stopwatch.java │ ├── StopwatchCPU.java │ ├── SuffixArray.java │ ├── SuffixArrayX.java │ ├── SymbolDigraph.java │ ├── SymbolGraph.java │ ├── TST.java │ ├── TarjanSCC.java │ ├── ThreeSum.java │ ├── ThreeSumFast.java │ ├── TopM.java │ ├── Topological.java │ ├── TopologicalX.java │ ├── Transaction.java │ ├── TransitiveClosure.java │ ├── TrieSET.java │ ├── TrieST.java │ ├── TwoPersonZeroSumGame.java │ ├── UF.java │ ├── Vector.java │ ├── WeightedQuickUnionUF.java │ ├── WhiteFilter.java │ └── Whitelist.java └── resources └── META-INF └── services └── com.cipher.spi.DemoService /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | /sandbox/*.iml 3 | target 4 | .DS_Store 5 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/A_Base/AlgoVisualizer.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.A_Base; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * @Author: CipherCui 7 | * @Description: 抽象控制层 8 | * @Date: Created in 15:18 2018/9/10 9 | */ 10 | public abstract class AlgoVisualizer { 11 | 12 | private Object data; 13 | private AlgoFrame frame; 14 | 15 | /** 16 | * 初始化数据 17 | * 18 | * @param sceneWidth 19 | * @param sceneHeight 20 | * @return 21 | */ 22 | public abstract Object initData(int sceneWidth, int sceneHeight); 23 | 24 | /** 25 | * 初始化窗口 frame 26 | * 27 | * @return 28 | */ 29 | public abstract AlgoFrame initFrame(int sceneWidth, int sceneHeight); 30 | 31 | /** 32 | * 动画逻辑 33 | * 34 | * @param data 35 | * @param frame 36 | */ 37 | public abstract void run(Object data, AlgoFrame frame); 38 | 39 | public AlgoVisualizer() { 40 | this(0, 0); 41 | } 42 | 43 | public AlgoVisualizer(int sceneWidth, int sceneHeight) { 44 | // 数据 45 | data = initData(sceneWidth, sceneHeight); 46 | // 视图 47 | EventQueue.invokeLater(() -> { 48 | frame = initFrame(sceneWidth, sceneHeight); 49 | // 动画逻辑 50 | new Thread(() -> run(data, frame)).start(); 51 | }); 52 | } 53 | 54 | public Object getData() { 55 | return data; 56 | } 57 | 58 | public AlgoFrame getFrame() { 59 | return frame; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/B_Circle/Circle.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.B_Circle; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * @Author: CipherCui 7 | * @Description: 圆圈 8 | * @Date: Created in 14:42 2018/9/10 9 | */ 10 | public class Circle { 11 | 12 | public int x, y; 13 | private int r; 14 | public int vx, vy; 15 | public boolean isFilled = false; 16 | 17 | public Circle(int x, int y, int r, int vx, int vy) { 18 | this.x = x; 19 | this.y = y; 20 | this.r = r; 21 | this.vx = vx; 22 | this.vy = vy; 23 | } 24 | 25 | public int getR() { 26 | return r; 27 | } 28 | 29 | public void move(int minx, int miny, int maxx, int maxy) { 30 | x += vx; 31 | y += vy; 32 | checkCollision(minx, miny, maxx, maxy); 33 | } 34 | 35 | public boolean contain(Point point) { 36 | return (x - point.x) * (x - point.x) + (y - point.y) * (y - point.y) <= r * r; 37 | } 38 | 39 | private void checkCollision(int minx, int miny, int maxx, int maxy) { 40 | if (x - r < minx) { 41 | x = r; 42 | vx = -vx; 43 | } 44 | if (x + r >= maxx) { 45 | x = maxx - r; 46 | vx = -vx; 47 | } 48 | if (y - r < miny) { 49 | y = r; 50 | vy = -vy; 51 | } 52 | if (y + r >= maxy) { 53 | y = maxy - r; 54 | vy = -vy; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/B_Circle/CircleFrame.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.B_Circle; 2 | 3 | import com.cipher.algorithm_visualization.A_Base.AlgoFrame; 4 | import com.cipher.algorithm_visualization.A_Base.AlgoVisHelper; 5 | 6 | import java.awt.*; 7 | 8 | /** 9 | * @Author: CipherCui 10 | * @Description: 圆圈窗口 11 | * @Date: Created in 11:13 2018/9/10 12 | */ 13 | public class CircleFrame extends AlgoFrame { 14 | 15 | public CircleFrame(String title, int canvasWidth, int canvasHeight) { 16 | super(title, canvasWidth, canvasHeight); 17 | } 18 | 19 | @Override 20 | public void paint(AlgoVisHelper algoVisHelper, Object data) { 21 | algoVisHelper.setStrokeWidth(1); 22 | algoVisHelper.setColor(Color.RED); 23 | Circle[] circles = (Circle[]) data; 24 | for (Circle c : circles) { 25 | if (c.isFilled) { 26 | algoVisHelper.fillCircle(c.x, c.y, c.getR()); 27 | } else { 28 | algoVisHelper.strokeCircle(c.x, c.y, c.getR()); 29 | } 30 | } 31 | } 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/C_Money/MoneyFrame.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.C_Money; 2 | 3 | import com.cipher.algorithm_visualization.A_Base.AlgoFrame; 4 | import com.cipher.algorithm_visualization.A_Base.AlgoVisHelper; 5 | 6 | /** 7 | * @Author: CipherCui 8 | * @Description: 9 | * @Date: Created in 14:28 2018/9/11 10 | */ 11 | public class MoneyFrame extends AlgoFrame { 12 | 13 | public MoneyFrame(String title, int canvasWidth, int canvasHeight) { 14 | super(title, canvasWidth, canvasHeight); 15 | } 16 | 17 | @Override 18 | public void paint(AlgoVisHelper algoVisHelper, Object data) { 19 | int[] money = (int[]) data; 20 | int w = getCanvasWidth() / money.length; 21 | for (int i = 0; i < money.length; i++) { 22 | if (money[i] > 0) { 23 | algoVisHelper.setColor(AlgoVisHelper.Blue); 24 | algoVisHelper.fillRectangle(i * w, getCanvasHeight() / 2 - money[i], w - 1, money[i]); 25 | } else if (money[i] < 0) { 26 | algoVisHelper.setColor(AlgoVisHelper.Red); 27 | algoVisHelper.fillRectangle(i * w, getCanvasHeight() / 2, w - 1, -money[i]); 28 | } 29 | } 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/D_Montecarlo/montyhall/ThreeGatesExperiment.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.D_Montecarlo.montyhall; 2 | 3 | 4 | /** 5 | * @Author: CipherCui 6 | * @Description: 三门问题 7 | * @Date: Created in 15:59 2018/9/14 8 | */ 9 | public class ThreeGatesExperiment { 10 | 11 | private int N; 12 | 13 | public ThreeGatesExperiment(int n) { 14 | N = n; 15 | } 16 | 17 | public void run(boolean changeDoor) { 18 | int wins = 0; 19 | for (int i = 0; i < N; i++) { 20 | if (play(changeDoor)) { 21 | wins++; 22 | } 23 | } 24 | System.out.println(changeDoor ? "Change" : "Not Change"); 25 | System.out.println("winning rate: " + (double) wins / N); 26 | } 27 | 28 | private boolean play(boolean changeDoor) { 29 | int winDoor = (int) (Math.random() * 3); 30 | int chooseDoor = (int) (Math.random() * 3); 31 | // 第一次选择是否赢 32 | boolean winAtFirst = winDoor == chooseDoor; 33 | // 换门:本来赢的变输,本来输的变赢 34 | // 不换门:本来赢就赢,输就输 35 | return changeDoor ? !winAtFirst : winAtFirst; 36 | } 37 | 38 | public static void main(String[] args) { 39 | int N = 1000000; 40 | ThreeGatesExperiment experiment = new ThreeGatesExperiment(N); 41 | experiment.run(true); 42 | experiment.run(false); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/D_Montecarlo/openbox/WinningPrice.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.D_Montecarlo.openbox; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: 开宝箱问题 6 | * @Date: Created in 13:53 2018/9/15 7 | */ 8 | public class WinningPrice { 9 | 10 | private double chance; 11 | private int playtime; 12 | private int N; 13 | 14 | public WinningPrice(double chance, int playtime, int n) { 15 | this.chance = chance; 16 | this.playtime = playtime; 17 | N = n; 18 | } 19 | 20 | public void run() { 21 | int wins = 0; 22 | for (int i = 0; i < N; i++) { 23 | if (play()) { 24 | wins++; 25 | } 26 | } 27 | System.out.println("winning rate: " + (double) wins / N); 28 | } 29 | 30 | private boolean play() { 31 | for (int i = 0; i < playtime; i++) { 32 | if (Math.random() < chance) { 33 | return true; 34 | } 35 | } 36 | return false; 37 | } 38 | 39 | public static void main(String[] args) { 40 | double chance = 0.2; 41 | int playtime = 5; 42 | int N = 1000000; 43 | WinningPrice price = new WinningPrice(chance, playtime, N); 44 | price.run(); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/D_Montecarlo/pi/Circle.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.D_Montecarlo.pi; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * @Author: CipherCui 7 | * @Description: 8 | * @Date: Created in 14:21 2018/9/13 9 | */ 10 | public class Circle { 11 | 12 | private int x, y, r; 13 | 14 | public Circle(int x, int y, int r){ 15 | this.x = x; 16 | this.y = y; 17 | this.r = r; 18 | } 19 | 20 | public int getX(){ return x; } 21 | public int getY(){ return y; } 22 | public int getR(){ return r; } 23 | 24 | public boolean contain(Point p){ 25 | return Math.pow(p.x - x, 2) + Math.pow(p.y - y, 2) <= r*r; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/D_Montecarlo/pi/MonteCarloExperiment.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.D_Montecarlo.pi; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * @Author: CipherCui 7 | * @Description: 不需要可视化的蒙特卡洛模拟 - 计算 pi 值 8 | * @Date: Created in 15:49 2018/9/13 9 | */ 10 | public class MonteCarloExperiment { 11 | 12 | public static void main(String[] args) { 13 | int squareSide = 800; 14 | int N = 10000000; 15 | Circle circle = new Circle(squareSide / 2, squareSide / 2, squareSide / 2); 16 | MonteCarloPiData piData = new MonteCarloPiData(circle); 17 | for (int i = 0; i < N; i++) { 18 | if (i % (N / 100) == 0) { 19 | System.out.println(piData.estimatePi()); 20 | } 21 | int x = (int) (Math.random() * squareSide); 22 | int y = (int) (Math.random() * squareSide); 23 | piData.addPoint(new Point(x, y)); 24 | } 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/D_Montecarlo/pi/MonteCarloPiData.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.D_Montecarlo.pi; 2 | 3 | import java.awt.*; 4 | import java.util.LinkedList; 5 | 6 | /** 7 | * @Author: CipherCui 8 | * @Description: 9 | * @Date: Created in 15:28 2018/9/13 10 | */ 11 | public class MonteCarloPiData { 12 | 13 | private Circle circle; 14 | private LinkedList points; 15 | private int insideCircle = 0; 16 | 17 | public MonteCarloPiData(Circle circle) { 18 | this.circle = circle; 19 | points = new LinkedList<>(); 20 | } 21 | 22 | public Circle getCircle() { 23 | return circle; 24 | } 25 | 26 | public int getPointsNumber() { 27 | return points.size(); 28 | } 29 | 30 | public Point getPoint(int i) { 31 | if (i < 0 || i >= points.size()) { 32 | throw new IllegalArgumentException("out of bound in getPoint!"); 33 | } 34 | return points.get(i); 35 | } 36 | 37 | public void addPoint(Point p) { 38 | points.add(p); 39 | if (circle.contain(p)) { 40 | insideCircle++; 41 | } 42 | } 43 | 44 | public double estimatePi() { 45 | if (points.size() == 0) { 46 | return 0.0; 47 | } 48 | int circleArea = insideCircle; 49 | int squareArea = points.size(); 50 | return (double) circleArea * 4 / squareArea; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/D_Montecarlo/pi/PiFrame.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.D_Montecarlo.pi; 2 | 3 | import com.cipher.algorithm_visualization.A_Base.AlgoFrame; 4 | import com.cipher.algorithm_visualization.A_Base.AlgoVisHelper; 5 | 6 | import java.awt.*; 7 | 8 | /** 9 | * @Author: CipherCui 10 | * @Description: 11 | * @Date: Created in 14:20 2018/9/13 12 | */ 13 | public class PiFrame extends AlgoFrame { 14 | 15 | public PiFrame(String title, int canvasWidth, int canvasHeight) { 16 | super(title, canvasWidth, canvasHeight); 17 | } 18 | 19 | @Override 20 | public void paint(AlgoVisHelper algoVisHelper, Object data) { 21 | MonteCarloPiData piData = (MonteCarloPiData) data; 22 | Circle circle = piData.getCircle(); 23 | algoVisHelper.setStrokeWidth(3); 24 | algoVisHelper.setColor(AlgoVisHelper.Blue); 25 | algoVisHelper.strokeCircle(circle.getX(), circle.getY(), circle.getR()); 26 | for (int i = 0; i < piData.getPointsNumber(); i++) { 27 | Point p = piData.getPoint(i); 28 | if (circle.contain(p)) { 29 | algoVisHelper.setColor(AlgoVisHelper.Red); 30 | } else { 31 | algoVisHelper.setColor(AlgoVisHelper.Green); 32 | } 33 | algoVisHelper.fillCircle((int) p.getX(), (int) p.getY(), 3); 34 | } 35 | algoVisHelper.setColor(AlgoVisHelper.Black); 36 | algoVisHelper.drawText(String.valueOf(piData.estimatePi()), circle.getX(), circle.getY()); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/E_Sort/heap/HeapSortData.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.E_Sort.heap; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: 6 | * @Date: Created in 14:44 2018/9/21 7 | */ 8 | public class HeapSortData { 9 | 10 | private int[] numbers; 11 | public int heapIndex; // numbers[heapIndex...N) 已经排好序 12 | 13 | public HeapSortData(int N, int randomBound) { 14 | numbers = new int[N]; 15 | heapIndex = N; 16 | for (int i = 0; i < N; i++) { 17 | numbers[i] = (int) (Math.random() * randomBound) + 1; 18 | } 19 | } 20 | 21 | public int N() { 22 | return numbers.length; 23 | } 24 | 25 | public int get(int index) { 26 | return numbers[index]; 27 | } 28 | 29 | public void swap(int i, int j) { 30 | int t = numbers[i]; 31 | numbers[i] = numbers[j]; 32 | numbers[j] = t; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/E_Sort/heap/HeapSortFrame.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.E_Sort.heap; 2 | 3 | import com.cipher.algorithm_visualization.A_Base.AlgoFrame; 4 | import com.cipher.algorithm_visualization.A_Base.AlgoVisHelper; 5 | 6 | /** 7 | * @Author: CipherCui 8 | * @Description: 9 | * @Date: Created in 14:46 2018/9/21 10 | */ 11 | public class HeapSortFrame extends AlgoFrame { 12 | 13 | public HeapSortFrame(String title, int canvasWidth, int canvasHeight) { 14 | super(title, canvasWidth, canvasHeight); 15 | } 16 | 17 | @Override 18 | public void paint(AlgoVisHelper algoVisHelper, Object data) { 19 | HeapSortData sortData = (HeapSortData) data; 20 | int w = getCanvasWidth() / sortData.N(); 21 | for (int i = 0; i < sortData.N(); i++) { 22 | if (i >= sortData.heapIndex) { 23 | algoVisHelper.setColor(AlgoVisHelper.Red); 24 | } else { 25 | algoVisHelper.setColor(AlgoVisHelper.Grey); 26 | } 27 | algoVisHelper.fillRectangle(i * w, getCanvasHeight() - sortData.get(i), w - 1, sortData.get(i)); 28 | } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/E_Sort/insertion/InsertionSortData.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.E_Sort.insertion; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @Author: CipherCui 7 | * @Description: 8 | * @Date: Created in 16:20 2018/9/17 9 | */ 10 | public class InsertionSortData { 11 | 12 | public enum Type { 13 | Default, 14 | NearlyOrdered 15 | } 16 | 17 | private int[] numbers; 18 | // [0...orderedIndex) 是有序的 19 | public int orderedIndex = -1; 20 | // 当前正在处理的元素的索引 21 | public int currentIndex = -1; 22 | 23 | public InsertionSortData(int N, int randomBound, Type dataType) { 24 | numbers = new int[N]; 25 | for (int i = 0; i < N; i++) { 26 | numbers[i] = (int) (Math.random() * randomBound) + 1; 27 | } 28 | if (dataType == Type.NearlyOrdered) { 29 | Arrays.sort(numbers); 30 | int swapTimes = (int) (0.02 * N); 31 | for (int i = 0; i < swapTimes; i++) { 32 | int a = (int) (Math.random() * N); 33 | int b = (int) (Math.random() * N); 34 | swap(a, b); 35 | } 36 | } 37 | } 38 | 39 | public InsertionSortData(int N, int randomBound) { 40 | this(N, randomBound, Type.Default); 41 | } 42 | 43 | public int N() { 44 | return numbers.length; 45 | } 46 | 47 | public int get(int index) { 48 | return numbers[index]; 49 | } 50 | 51 | public void swap(int i, int j) { 52 | int temp = numbers[i]; 53 | numbers[i] = numbers[j]; 54 | numbers[j] = temp; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/E_Sort/insertion/InsertionSortFrame.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.E_Sort.insertion; 2 | 3 | import com.cipher.algorithm_visualization.A_Base.AlgoFrame; 4 | import com.cipher.algorithm_visualization.A_Base.AlgoVisHelper; 5 | 6 | /** 7 | * @Author: CipherCui 8 | * @Description: 9 | * @Date: Created in 16:23 2018/9/17 10 | */ 11 | public class InsertionSortFrame extends AlgoFrame { 12 | 13 | public InsertionSortFrame(String title, int canvasWidth, int canvasHeight) { 14 | super(title, canvasWidth, canvasHeight); 15 | } 16 | 17 | @Override 18 | public void paint(AlgoVisHelper algoVisHelper, Object data) { 19 | InsertionSortData sortData = (InsertionSortData) data; 20 | int w = getCanvasWidth() / sortData.N(); 21 | for (int i = 0; i < sortData.N(); i++) { 22 | if (i < sortData.orderedIndex) { 23 | algoVisHelper.setColor(AlgoVisHelper.Red); 24 | } else { 25 | algoVisHelper.setColor(AlgoVisHelper.Grey); 26 | } 27 | if (i == sortData.currentIndex) { 28 | algoVisHelper.setColor(AlgoVisHelper.LightBlue); 29 | } 30 | algoVisHelper.fillRectangle(i * w, getCanvasHeight() - sortData.get(i), w - 1, sortData.get(i)); 31 | } 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/E_Sort/merge/MergeSortData.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.E_Sort.merge; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: 6 | * @Date: Created in 14:03 2018/9/18 7 | */ 8 | public class MergeSortData { 9 | 10 | public int[] numbers; 11 | public int l, r; 12 | public int mergeIndex; 13 | 14 | public MergeSortData(int N, int randomBound) { 15 | numbers = new int[N]; 16 | for (int i = 0; i < N; i++) { 17 | numbers[i] = (int) (Math.random() * randomBound) + 1; 18 | } 19 | } 20 | 21 | public int N() { 22 | return numbers.length; 23 | } 24 | 25 | public int get(int index) { 26 | return numbers[index]; 27 | } 28 | 29 | public void swap(int i, int j) { 30 | int temp = numbers[i]; 31 | numbers[i] = numbers[j]; 32 | numbers[j] = temp; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/E_Sort/merge/MergeSortFrame.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.E_Sort.merge; 2 | 3 | import com.cipher.algorithm_visualization.A_Base.AlgoFrame; 4 | import com.cipher.algorithm_visualization.A_Base.AlgoVisHelper; 5 | 6 | /** 7 | * @Author: CipherCui 8 | * @Description: 9 | * @Date: Created in 15:02 2018/9/18 10 | */ 11 | public class MergeSortFrame extends AlgoFrame { 12 | 13 | public MergeSortFrame(String title, int canvasWidth, int canvasHeight) { 14 | super(title, canvasWidth, canvasHeight); 15 | } 16 | 17 | @Override 18 | public void paint(AlgoVisHelper algoVisHelper, Object data) { 19 | MergeSortData sortData = (MergeSortData) data; 20 | int w = getCanvasWidth() / sortData.N(); 21 | for (int i = 0; i < sortData.N(); i++) { 22 | if (i >= sortData.l && i <= sortData.r) { 23 | algoVisHelper.setColor(AlgoVisHelper.Green); 24 | } else { 25 | algoVisHelper.setColor(AlgoVisHelper.Grey); 26 | } 27 | if (i >= sortData.l && i <= sortData.mergeIndex) { 28 | algoVisHelper.setColor(AlgoVisHelper.Red); 29 | } 30 | algoVisHelper.fillRectangle(i * w, getCanvasHeight() - sortData.get(i), w - 1, sortData.get(i)); 31 | } 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/E_Sort/quick/simple/QuickSortDataSimple.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.E_Sort.quick.simple; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @Author: CipherCui 7 | * @Description: 8 | * @Date: Created in 13:53 2018/9/19 9 | */ 10 | public class QuickSortDataSimple { 11 | 12 | public enum Type { 13 | Default, 14 | NearlyOrdered 15 | } 16 | 17 | public int[] numbers; 18 | public int l, r; 19 | public int curPivot; 20 | public int curElement; 21 | public boolean[] fixedPivot; 22 | 23 | public QuickSortDataSimple(int N, int randomBound, Type dataType) { 24 | numbers = new int[N]; 25 | fixedPivot = new boolean[N]; 26 | for (int i = 0; i < N; i++) { 27 | numbers[i] = (int) (Math.random() * randomBound) + 1; 28 | fixedPivot[i] = false; 29 | } 30 | if (dataType == Type.NearlyOrdered) { 31 | Arrays.sort(numbers); 32 | int swapTimes = (int) (0.01 * N); 33 | for (int i = 0; i < swapTimes; i++) { 34 | int a = (int) (Math.random() * N); 35 | int b = (int) (Math.random() * N); 36 | swap(a, b); 37 | } 38 | } 39 | } 40 | 41 | public QuickSortDataSimple(int N, int randomBound) { 42 | this(N, randomBound, Type.Default); 43 | } 44 | 45 | public int N() { 46 | return numbers.length; 47 | } 48 | 49 | public int get(int index) { 50 | return numbers[index]; 51 | } 52 | 53 | public void swap(int i, int j) { 54 | int temp = numbers[i]; 55 | numbers[i] = numbers[j]; 56 | numbers[j] = temp; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/E_Sort/quick/simple/QuickSortFrameSimple.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.E_Sort.quick.simple; 2 | 3 | import com.cipher.algorithm_visualization.A_Base.AlgoFrame; 4 | import com.cipher.algorithm_visualization.A_Base.AlgoVisHelper; 5 | 6 | /** 7 | * @Author: CipherCui 8 | * @Description: 9 | * @Date: Created in 14:09 2018/9/19 10 | */ 11 | public class QuickSortFrameSimple extends AlgoFrame { 12 | 13 | public QuickSortFrameSimple(String title, int canvasWidth, int canvasHeight) { 14 | super(title, canvasWidth, canvasHeight); 15 | } 16 | 17 | @Override 18 | public void paint(AlgoVisHelper algoVisHelper, Object data) { 19 | QuickSortDataSimple sortData = (QuickSortDataSimple) data; 20 | int w = getCanvasWidth() / sortData.N(); 21 | for (int i = 0; i < sortData.N(); i++) { 22 | if (i >= sortData.l && i <= sortData.r) { 23 | algoVisHelper.setColor(AlgoVisHelper.Green); 24 | } else { 25 | algoVisHelper.setColor(AlgoVisHelper.Grey); 26 | } 27 | if (i == sortData.curPivot) { 28 | algoVisHelper.setColor(AlgoVisHelper.Indigo); 29 | } 30 | if (i == sortData.curElement) { 31 | algoVisHelper.setColor(AlgoVisHelper.LightBlue); 32 | } 33 | if (sortData.fixedPivot[i]) { 34 | algoVisHelper.setColor(AlgoVisHelper.Red); 35 | } 36 | algoVisHelper.fillRectangle(i * w, getCanvasHeight() - sortData.get(i), w - 1, sortData.get(i)); 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/E_Sort/quick/three_ways/QuickSortFrame3Way.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.E_Sort.quick.three_ways; 2 | 3 | import com.cipher.algorithm_visualization.A_Base.AlgoFrame; 4 | import com.cipher.algorithm_visualization.A_Base.AlgoVisHelper; 5 | 6 | /** 7 | * @Author: CipherCui 8 | * @Description: 9 | * @Date: Created in 14:09 2018/9/19 10 | */ 11 | public class QuickSortFrame3Way extends AlgoFrame { 12 | 13 | public QuickSortFrame3Way(String title, int canvasWidth, int canvasHeight) { 14 | super(title, canvasWidth, canvasHeight); 15 | } 16 | 17 | @Override 18 | public void paint(AlgoVisHelper algoVisHelper, Object data) { 19 | QuickSortData3Way sortData = (QuickSortData3Way) data; 20 | int w = getCanvasWidth() / sortData.N(); 21 | for (int i = 0; i < sortData.N(); i++) { 22 | if (i >= sortData.l && i <= sortData.r) { 23 | algoVisHelper.setColor(AlgoVisHelper.Green); 24 | } else { 25 | algoVisHelper.setColor(AlgoVisHelper.Grey); 26 | } 27 | if (i == sortData.curPivot) { 28 | algoVisHelper.setColor(AlgoVisHelper.Indigo); 29 | } 30 | if (i >= sortData.l + 1 && i <= sortData.curL) { 31 | algoVisHelper.setColor(AlgoVisHelper.LightBlue); 32 | } 33 | if (i >= sortData.curR && i <= sortData.r) { 34 | algoVisHelper.setColor(AlgoVisHelper.LightBlue); 35 | } 36 | if (sortData.fixedPivots[i]) { 37 | algoVisHelper.setColor(AlgoVisHelper.Red); 38 | } 39 | algoVisHelper.fillRectangle(i * w, getCanvasHeight() - sortData.get(i), w - 1, sortData.get(i)); 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/E_Sort/quick/two_ways/QuickSortFrame2Way.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.E_Sort.quick.two_ways; 2 | 3 | import com.cipher.algorithm_visualization.A_Base.AlgoFrame; 4 | import com.cipher.algorithm_visualization.A_Base.AlgoVisHelper; 5 | 6 | /** 7 | * @Author: CipherCui 8 | * @Description: 9 | * @Date: Created in 14:09 2018/9/19 10 | */ 11 | public class QuickSortFrame2Way extends AlgoFrame { 12 | 13 | public QuickSortFrame2Way(String title, int canvasWidth, int canvasHeight) { 14 | super(title, canvasWidth, canvasHeight); 15 | } 16 | 17 | @Override 18 | public void paint(AlgoVisHelper algoVisHelper, Object data) { 19 | QuickSortData2Way sortData = (QuickSortData2Way) data; 20 | int w = getCanvasWidth() / sortData.N(); 21 | for (int i = 0; i < sortData.N(); i++) { 22 | if (i >= sortData.l && i <= sortData.r) { 23 | algoVisHelper.setColor(AlgoVisHelper.Green); 24 | } else { 25 | algoVisHelper.setColor(AlgoVisHelper.Grey); 26 | } 27 | if (i == sortData.curPivot) { 28 | algoVisHelper.setColor(AlgoVisHelper.Indigo); 29 | } 30 | if (i >= sortData.l + 1 && i <= sortData.curL) { 31 | algoVisHelper.setColor(AlgoVisHelper.LightBlue); 32 | } 33 | if (i >= sortData.curR && i <= sortData.r) { 34 | algoVisHelper.setColor(AlgoVisHelper.LightBlue); 35 | } 36 | if (sortData.fixedPivots[i]) { 37 | algoVisHelper.setColor(AlgoVisHelper.Red); 38 | } 39 | algoVisHelper.fillRectangle(i * w, getCanvasHeight() - sortData.get(i), w - 1, sortData.get(i)); 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/E_Sort/quick/with_random_pivot/QuickSortFrameRandom.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.E_Sort.quick.with_random_pivot; 2 | 3 | import com.cipher.algorithm_visualization.A_Base.AlgoFrame; 4 | import com.cipher.algorithm_visualization.A_Base.AlgoVisHelper; 5 | 6 | /** 7 | * @Author: CipherCui 8 | * @Description: 9 | * @Date: Created in 14:09 2018/9/19 10 | */ 11 | public class QuickSortFrameRandom extends AlgoFrame { 12 | 13 | public QuickSortFrameRandom(String title, int canvasWidth, int canvasHeight) { 14 | super(title, canvasWidth, canvasHeight); 15 | } 16 | 17 | @Override 18 | public void paint(AlgoVisHelper algoVisHelper, Object data) { 19 | QuickSortDataRandom sortData = (QuickSortDataRandom) data; 20 | int w = getCanvasWidth() / sortData.N(); 21 | for (int i = 0; i < sortData.N(); i++) { 22 | if (i >= sortData.l && i <= sortData.r) { 23 | algoVisHelper.setColor(AlgoVisHelper.Green); 24 | } else { 25 | algoVisHelper.setColor(AlgoVisHelper.Grey); 26 | } 27 | if (i == sortData.curPivot) { 28 | algoVisHelper.setColor(AlgoVisHelper.Indigo); 29 | } 30 | if (i == sortData.curElement) { 31 | algoVisHelper.setColor(AlgoVisHelper.LightBlue); 32 | } 33 | if (sortData.fixedPivot[i]) { 34 | algoVisHelper.setColor(AlgoVisHelper.Red); 35 | } 36 | algoVisHelper.fillRectangle(i * w, getCanvasHeight() - sortData.get(i), w - 1, sortData.get(i)); 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/E_Sort/selection/SelectionSortData.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.E_Sort.selection; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: 6 | * @Date: Created in 17:31 2018/9/15 7 | */ 8 | public class SelectionSortData { 9 | 10 | private int[] numbers; 11 | // [0...orderedIndex) 是有序的 12 | public int orderedIndex = -1; 13 | // 当前找到的最小元素的索引 14 | public int currentMinIndex = -1; 15 | // 当前正在比较的元素索引 16 | public int currentCompareIndex = -1; 17 | 18 | public SelectionSortData(int N, int randomBound) { 19 | numbers = new int[N]; 20 | for (int i = 0; i < N; i++) { 21 | numbers[i] = (int) (Math.random() * randomBound) + 1; 22 | } 23 | } 24 | 25 | public int N() { 26 | return numbers.length; 27 | } 28 | 29 | public int get(int index) { 30 | return numbers[index]; 31 | } 32 | 33 | public void swap(int i, int j) { 34 | int temp = numbers[i]; 35 | numbers[i] = numbers[j]; 36 | numbers[j] = temp; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/E_Sort/selection/SelectionSortFrame.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.E_Sort.selection; 2 | 3 | import com.cipher.algorithm_visualization.A_Base.AlgoFrame; 4 | import com.cipher.algorithm_visualization.A_Base.AlgoVisHelper; 5 | 6 | /** 7 | * @Author: CipherCui 8 | * @Description: 9 | * @Date: Created in 17:37 2018/9/15 10 | */ 11 | public class SelectionSortFrame extends AlgoFrame { 12 | 13 | public SelectionSortFrame(String title, int canvasWidth, int canvasHeight) { 14 | super(title, canvasWidth, canvasHeight); 15 | } 16 | 17 | @Override 18 | public void paint(AlgoVisHelper algoVisHelper, Object data) { 19 | SelectionSortData sortData = (SelectionSortData) data; 20 | int w = getCanvasWidth() / sortData.N(); 21 | for (int i = 0; i < sortData.N(); i++) { 22 | if (i < sortData.orderedIndex) { 23 | algoVisHelper.setColor(AlgoVisHelper.Red); 24 | } else { 25 | algoVisHelper.setColor(AlgoVisHelper.Grey); 26 | } 27 | if (i == sortData.currentCompareIndex) { 28 | algoVisHelper.setColor(AlgoVisHelper.LightBlue); 29 | } 30 | if (i == sortData.currentMinIndex) { 31 | algoVisHelper.setColor(AlgoVisHelper.Indigo); 32 | } 33 | algoVisHelper.fillRectangle(i * w, getCanvasHeight() - sortData.get(i), w - 1, sortData.get(i)); 34 | } 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/F_Maze/MazeFrame.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.F_Maze; 2 | 3 | import com.cipher.algorithm_visualization.A_Base.AlgoFrame; 4 | import com.cipher.algorithm_visualization.A_Base.AlgoVisHelper; 5 | 6 | /** 7 | * @Author: CipherCui 8 | * @Description: 9 | * @Date: Created in 11:35 2018/9/27 10 | */ 11 | public class MazeFrame extends AlgoFrame { 12 | 13 | public MazeFrame(String title, int canvasWidth, int canvasHeight) { 14 | super(title, canvasWidth, canvasHeight); 15 | } 16 | 17 | @Override 18 | public void paint(AlgoVisHelper algoVisHelper, Object data) { 19 | MazeData mazeData = (MazeData) data; 20 | int w = getCanvasWidth() / mazeData.M(); 21 | int h = getCanvasHeight() / mazeData.N(); 22 | for (int i = 0; i < mazeData.N(); i++) { 23 | for (int j = 0; j < mazeData.M(); j++) { 24 | if (mazeData.getMaze(i, j) == MazeData.WALL) { 25 | algoVisHelper.setColor(AlgoVisHelper.LightBlue); 26 | } else { 27 | algoVisHelper.setColor(AlgoVisHelper.White); 28 | } 29 | if (mazeData.path[i][j]) { 30 | algoVisHelper.setColor(AlgoVisHelper.Yellow); 31 | } 32 | if (mazeData.result[i][j]) { 33 | algoVisHelper.setColor(AlgoVisHelper.Red); 34 | } 35 | algoVisHelper.fillRectangle(j * w, i * h, w, h); 36 | } 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/G_Build_Maze/MazeFrame.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.G_Build_Maze; 2 | 3 | import com.cipher.algorithm_visualization.A_Base.AlgoFrame; 4 | import com.cipher.algorithm_visualization.A_Base.AlgoVisHelper; 5 | 6 | /** 7 | * @Author: CipherCui 8 | * @Description: 9 | * @Date: Created in 11:35 2018/9/27 10 | */ 11 | public class MazeFrame extends AlgoFrame { 12 | 13 | public MazeFrame(String title, int canvasWidth, int canvasHeight) { 14 | super(title, canvasWidth, canvasHeight); 15 | } 16 | 17 | @Override 18 | public void paint(AlgoVisHelper algoVisHelper, Object data) { 19 | MazeData mazeData = (MazeData) data; 20 | int w = getCanvasWidth() / mazeData.M(); 21 | int h = getCanvasHeight() / mazeData.N(); 22 | for (int i = 0; i < mazeData.N(); i++) { 23 | for (int j = 0; j < mazeData.M(); j++) { 24 | if (mazeData.enableMist && mazeData.inMist[i][j]) { 25 | algoVisHelper.setColor(AlgoVisHelper.Black); 26 | } else { 27 | if (mazeData.maze[i][j] == MazeData.WALL) { 28 | algoVisHelper.setColor(AlgoVisHelper.LightBlue); 29 | } else { 30 | algoVisHelper.setColor(AlgoVisHelper.White); 31 | } 32 | if (mazeData.path[i][j]) { 33 | algoVisHelper.setColor(AlgoVisHelper.Yellow); 34 | } 35 | } 36 | algoVisHelper.fillRectangle(j * w, i * h, w, h); 37 | } 38 | } 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/G_Build_Maze/random_1/RandomQueue.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.G_Build_Maze.random_1; 2 | 3 | import org.springframework.util.CollectionUtils; 4 | 5 | import java.util.ArrayList; 6 | 7 | /** 8 | * @Author: CipherCui 9 | * @Description: 随机队列 10 | * @Date: Created in 13:53 2018/10/9 11 | */ 12 | public class RandomQueue { 13 | 14 | private ArrayList queue; 15 | 16 | public RandomQueue() { 17 | this.queue = new ArrayList<>(); 18 | } 19 | 20 | public void add(E e) { 21 | this.queue.add(e); 22 | } 23 | 24 | public E remove() { 25 | if (CollectionUtils.isEmpty(queue)) { 26 | throw new IllegalArgumentException("There's no element to remove in Random Queue"); 27 | } 28 | int randIndex = (int) (Math.random() * queue.size()); 29 | E randElement = queue.get(randIndex); 30 | queue.set(randIndex, queue.get(queue.size() - 1)); 31 | queue.remove(queue.size() - 1); 32 | return randElement; 33 | } 34 | 35 | public int size() { 36 | return queue.size(); 37 | } 38 | 39 | public boolean empty() { 40 | return CollectionUtils.isEmpty(queue); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/G_Build_Maze/random_2/RandomQueue2.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.G_Build_Maze.random_2; 2 | 3 | import org.springframework.util.CollectionUtils; 4 | 5 | import java.util.LinkedList; 6 | 7 | /** 8 | * @Author: CipherCui 9 | * @Description: 随机队列2 10 | * @Date: Created in 13:53 2018/10/9 11 | */ 12 | public class RandomQueue2 { 13 | 14 | private LinkedList queue; 15 | 16 | private static final double FACTOR = 0.5; 17 | 18 | public RandomQueue2() { 19 | this.queue = new LinkedList<>(); 20 | } 21 | 22 | public void add(E e) { 23 | if (Math.random() < FACTOR) { 24 | queue.addFirst(e); 25 | } else { 26 | queue.addLast(e); 27 | } 28 | } 29 | 30 | public E remove() { 31 | if (CollectionUtils.isEmpty(queue)) { 32 | throw new IllegalArgumentException("There's no element to remove in Random Queue"); 33 | } 34 | if (Math.random() > FACTOR) { 35 | return queue.removeFirst(); 36 | } else { 37 | return queue.removeLast(); 38 | } 39 | } 40 | 41 | public int size() { 42 | return queue.size(); 43 | } 44 | 45 | public boolean empty() { 46 | return CollectionUtils.isEmpty(queue); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/H_Mine_Sweeper/MineSweeperFrame.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.H_Mine_Sweeper; 2 | 3 | import com.cipher.algorithm_visualization.A_Base.AlgoFrame; 4 | import com.cipher.algorithm_visualization.A_Base.AlgoVisHelper; 5 | 6 | /** 7 | * @Author: CipherCui 8 | * @Description: 9 | * @Date: Created in 13:39 2018/10/10 10 | */ 11 | public class MineSweeperFrame extends AlgoFrame { 12 | 13 | public MineSweeperFrame(String title, int canvasWidth, int canvasHeight) { 14 | super(title, canvasWidth, canvasHeight); 15 | } 16 | 17 | @Override 18 | public void paint(AlgoVisHelper algoVisHelper, Object obj) { 19 | MineSweeperData data = (MineSweeperData) obj; 20 | int w = getCanvasWidth() / data.M(); 21 | int h = getCanvasHeight() / data.N(); 22 | for (int i = 0; i < data.N(); i++) { 23 | for (int j = 0; j < data.M(); j++) { 24 | if (data.open[i][j]) { 25 | if (data.isMine(i, j)) { 26 | algoVisHelper.putImage(j * w, i * h, MineSweeperData.MINE_IMAGE_URL); 27 | } else { 28 | algoVisHelper.putImage(j * w, i * h, MineSweeperData.numberImageURL(data.getNumber(i, j))); 29 | } 30 | } else { 31 | if (data.flags[i][j]) { 32 | algoVisHelper.putImage(j * w, i * h, MineSweeperData.FLAG_IMAGE_URL); 33 | } else { 34 | algoVisHelper.putImage(j * w, i * h, MineSweeperData.BLOCK_IMAGE_URL); 35 | } 36 | } 37 | } 38 | } 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/H_Mine_Sweeper/images/0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ciphermagic/java-learn/fabffbbfd3c0093ba9717c3f94fc30f646f8b417/sandbox/src/main/java/com/cipher/algorithm_visualization/H_Mine_Sweeper/images/0.png -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/H_Mine_Sweeper/images/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ciphermagic/java-learn/fabffbbfd3c0093ba9717c3f94fc30f646f8b417/sandbox/src/main/java/com/cipher/algorithm_visualization/H_Mine_Sweeper/images/1.png -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/H_Mine_Sweeper/images/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ciphermagic/java-learn/fabffbbfd3c0093ba9717c3f94fc30f646f8b417/sandbox/src/main/java/com/cipher/algorithm_visualization/H_Mine_Sweeper/images/2.png -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/H_Mine_Sweeper/images/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ciphermagic/java-learn/fabffbbfd3c0093ba9717c3f94fc30f646f8b417/sandbox/src/main/java/com/cipher/algorithm_visualization/H_Mine_Sweeper/images/3.png -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/H_Mine_Sweeper/images/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ciphermagic/java-learn/fabffbbfd3c0093ba9717c3f94fc30f646f8b417/sandbox/src/main/java/com/cipher/algorithm_visualization/H_Mine_Sweeper/images/4.png -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/H_Mine_Sweeper/images/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ciphermagic/java-learn/fabffbbfd3c0093ba9717c3f94fc30f646f8b417/sandbox/src/main/java/com/cipher/algorithm_visualization/H_Mine_Sweeper/images/5.png -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/H_Mine_Sweeper/images/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ciphermagic/java-learn/fabffbbfd3c0093ba9717c3f94fc30f646f8b417/sandbox/src/main/java/com/cipher/algorithm_visualization/H_Mine_Sweeper/images/6.png -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/H_Mine_Sweeper/images/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ciphermagic/java-learn/fabffbbfd3c0093ba9717c3f94fc30f646f8b417/sandbox/src/main/java/com/cipher/algorithm_visualization/H_Mine_Sweeper/images/7.png -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/H_Mine_Sweeper/images/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ciphermagic/java-learn/fabffbbfd3c0093ba9717c3f94fc30f646f8b417/sandbox/src/main/java/com/cipher/algorithm_visualization/H_Mine_Sweeper/images/8.png -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/H_Mine_Sweeper/images/block.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ciphermagic/java-learn/fabffbbfd3c0093ba9717c3f94fc30f646f8b417/sandbox/src/main/java/com/cipher/algorithm_visualization/H_Mine_Sweeper/images/block.png -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/H_Mine_Sweeper/images/flag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ciphermagic/java-learn/fabffbbfd3c0093ba9717c3f94fc30f646f8b417/sandbox/src/main/java/com/cipher/algorithm_visualization/H_Mine_Sweeper/images/flag.png -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/H_Mine_Sweeper/images/mine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ciphermagic/java-learn/fabffbbfd3c0093ba9717c3f94fc30f646f8b417/sandbox/src/main/java/com/cipher/algorithm_visualization/H_Mine_Sweeper/images/mine.png -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/I_Move_Box/level/boston_08.txt: -------------------------------------------------------------------------------- 1 | 1 2 | ....... 3 | ...A... 4 | ...C... 5 | ..ABC.. 6 | ..BCB.. 7 | .ABABC. 8 | .AABCC. -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/I_Move_Box/level/boston_09.txt: -------------------------------------------------------------------------------- 1 | 1 2 | ..... 3 | ..A.. 4 | ..B.. 5 | ..A.. 6 | ..B.. 7 | .BAB. 8 | .BAB. 9 | .ABA. -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/I_Move_Box/level/boston_16.txt: -------------------------------------------------------------------------------- 1 | 2 2 | ......... 3 | ....A.... 4 | ...BCB... 5 | ...ADA... 6 | ..BDECB.. 7 | ..DFAFC.. 8 | .BAAEFEB. -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/I_Move_Box/level/newyork_04.txt: -------------------------------------------------------------------------------- 1 | 2 2 | ...D.. 3 | ...D.. 4 | ..DE.. 5 | .DEB.. 6 | .EDC.. 7 | .DAD.. 8 | DBDD.. 9 | AABCC. -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/I_Move_Box/level/newyork_05.txt: -------------------------------------------------------------------------------- 1 | 2 2 | .....C. 3 | ...A.D. 4 | ..ABCB. 5 | .ABCDD. -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/I_Move_Box/level/newyork_06.txt: -------------------------------------------------------------------------------- 1 | 2 2 | ....D. 3 | ....B. 4 | ...BD. 5 | ..BCB. 6 | .BDAC. 7 | .AABC. -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/J_Fractal_Drawing/recursive_circle/CircleData.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.J_Fractal_Drawing.recursive_circle; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: 6 | * @Date: Created in 11:41 2018/10/15 7 | */ 8 | public class CircleData { 9 | 10 | private int startX, startY; 11 | private int startR; 12 | private int depth; 13 | private int step; 14 | 15 | public CircleData(int x, int y, int r, int d, int step) { 16 | this.startX = x; 17 | this.startY = y; 18 | this.startR = r; 19 | this.depth = d; 20 | this.step = step; 21 | } 22 | 23 | public int getStartX() { 24 | return startX; 25 | } 26 | 27 | public int getStartY() { 28 | return startY; 29 | } 30 | 31 | public int getStartR() { 32 | return startR; 33 | } 34 | 35 | public int getDepth() { 36 | return depth; 37 | } 38 | 39 | public int getStep() { 40 | return step; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/J_Fractal_Drawing/recursive_circle/CircleFrame.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.J_Fractal_Drawing.recursive_circle; 2 | 3 | import com.cipher.algorithm_visualization.A_Base.AlgoFrame; 4 | import com.cipher.algorithm_visualization.A_Base.AlgoVisHelper; 5 | 6 | /** 7 | * @Author: CipherCui 8 | * @Description: 9 | * @Date: Created in 11:48 2018/10/15 10 | */ 11 | public class CircleFrame extends AlgoFrame { 12 | 13 | public CircleFrame(String title, int canvasWidth, int canvasHeight) { 14 | super(title, canvasWidth, canvasHeight); 15 | } 16 | 17 | @Override 18 | public void paint(AlgoVisHelper algoVisHelper, Object obj) { 19 | CircleData data = (CircleData) obj; 20 | drawCircle(algoVisHelper, data.getStartX(), data.getStartY(), data.getStartR(), 0); 21 | } 22 | 23 | private void drawCircle(AlgoVisHelper g, int x, int y, int r, int depth) { 24 | CircleData data = (CircleData) getData(); 25 | if (depth == data.getDepth() || r < 1) { 26 | return; 27 | } 28 | if (depth % 2 == 0) { 29 | g.setColor(AlgoVisHelper.Red); 30 | } else { 31 | g.setColor(AlgoVisHelper.LightBlue); 32 | } 33 | g.fillCircle(x, y, r); 34 | drawCircle(g, x, y, r - data.getStep(), depth + 1); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/J_Fractal_Drawing/recursive_circle/CircleVisualizer.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.J_Fractal_Drawing.recursive_circle; 2 | 3 | import com.cipher.algorithm_visualization.A_Base.AlgoFrame; 4 | import com.cipher.algorithm_visualization.A_Base.AlgoVisualizer; 5 | 6 | /** 7 | * @Author: CipherCui 8 | * @Description: 9 | * @Date: Created in 11:47 2018/10/15 10 | */ 11 | public class CircleVisualizer extends AlgoVisualizer { 12 | 13 | public CircleVisualizer(int sceneWidth, int sceneHeight) { 14 | super(sceneWidth, sceneHeight); 15 | } 16 | 17 | @Override 18 | public Object initData(int sceneWidth, int sceneHeight) { 19 | int R = Math.min(sceneWidth, sceneHeight) / 2 - 2; 20 | return new CircleData(sceneWidth / 2, sceneHeight / 2, R, R / 2, 2); 21 | } 22 | 23 | @Override 24 | public AlgoFrame initFrame(int sceneWidth, int sceneHeight) { 25 | return new CircleFrame("Fractal Visualizer", sceneWidth, sceneHeight); 26 | } 27 | 28 | @Override 29 | public void run(Object data, AlgoFrame frame) { 30 | frame.render(data); 31 | } 32 | 33 | public static void main(String[] args) { 34 | new CircleVisualizer(800, 800); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/J_Fractal_Drawing/sierpinski_carpet/CarpetData.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.J_Fractal_Drawing.sierpinski_carpet; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: 6 | * @Date: Created in 13:52 2018/10/15 7 | */ 8 | public class CarpetData { 9 | 10 | public int depth; 11 | 12 | public CarpetData(int depth) { 13 | this.depth = depth; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/J_Fractal_Drawing/sierpinski_carpet/CarpetFrame.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.J_Fractal_Drawing.sierpinski_carpet; 2 | 3 | import com.cipher.algorithm_visualization.A_Base.AlgoFrame; 4 | import com.cipher.algorithm_visualization.A_Base.AlgoVisHelper; 5 | 6 | /** 7 | * @Author: CipherCui 8 | * @Description: 9 | * @Date: Created in 13:55 2018/10/15 10 | */ 11 | public class CarpetFrame extends AlgoFrame { 12 | 13 | public CarpetFrame(String title, int canvasWidth, int canvasHeight) { 14 | super(title, canvasWidth, canvasHeight); 15 | } 16 | 17 | @Override 18 | public void paint(AlgoVisHelper algoVisHelper, Object obj) { 19 | drawFractal(algoVisHelper, 0, 0, getCanvasWidth(), getCanvasHeight(), 0); 20 | } 21 | 22 | private void drawFractal(AlgoVisHelper g, int x, int y, int w, int h, int depth) { 23 | CarpetData data = (CarpetData) getData(); 24 | int w_3 = w / 3; 25 | int h_3 = h / 3; 26 | if (depth == data.depth) { 27 | g.setColor(AlgoVisHelper.Indigo); 28 | g.fillRectangle(x + w_3, y + h_3, w_3, h_3); 29 | return; 30 | } 31 | if (w <= 1 || h <= 1) { 32 | return; 33 | } 34 | for (int i = 0; i < 3; i++) { 35 | for (int j = 0; j < 3; j++) { 36 | if (i == 1 && j == 1) { 37 | g.setColor(AlgoVisHelper.Indigo); 38 | g.fillRectangle(x + w_3, y + h_3, w_3, h_3); 39 | } else { 40 | drawFractal(g, x + i * w_3, y + j * h_3, w_3, h_3, depth + 1); 41 | } 42 | } 43 | } 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/J_Fractal_Drawing/sierpinski_triangle/TriangleData.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.J_Fractal_Drawing.sierpinski_triangle; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: 6 | * @Date: Created in 13:52 2018/10/15 7 | */ 8 | public class TriangleData { 9 | 10 | public int depth; 11 | 12 | public TriangleData(int depth) { 13 | this.depth = depth; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/J_Fractal_Drawing/snowflake_fractal/SnowflakeData.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.J_Fractal_Drawing.snowflake_fractal; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: 6 | * @Date: Created in 13:52 2018/10/15 7 | */ 8 | public class SnowflakeData { 9 | 10 | public int depth; 11 | 12 | public SnowflakeData(int depth) { 13 | this.depth = depth; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/J_Fractal_Drawing/tree_fractal/TreeData.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.J_Fractal_Drawing.tree_fractal; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: 6 | * @Date: Created in 13:52 2018/10/15 7 | */ 8 | public class TreeData { 9 | 10 | public int depth; 11 | public double splitAngle; 12 | 13 | public TreeData(int depth, double splitAngle) { 14 | this.depth = depth; 15 | this.splitAngle = splitAngle; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/J_Fractal_Drawing/tree_fractal/TreeFrame.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.J_Fractal_Drawing.tree_fractal; 2 | 3 | import com.cipher.algorithm_visualization.A_Base.AlgoFrame; 4 | import com.cipher.algorithm_visualization.A_Base.AlgoVisHelper; 5 | 6 | /** 7 | * @Author: CipherCui 8 | * @Description: 9 | * @Date: Created in 13:53 2018/10/15 10 | */ 11 | public class TreeFrame extends AlgoFrame { 12 | 13 | public TreeFrame(String title, int canvasWidth, int canvasHeight) { 14 | super(title, canvasWidth, canvasHeight); 15 | } 16 | 17 | @Override 18 | public void paint(AlgoVisHelper g, Object obj) { 19 | drawFractal(g, getCanvasWidth() / 2, getCanvasHeight(), getCanvasHeight(), 0, 0); 20 | } 21 | 22 | private void drawFractal(AlgoVisHelper g, double x1, double y1, double side, double angle, int depth) { 23 | TreeData data = (TreeData) getData(); 24 | if (side <= 0) { 25 | return; 26 | } 27 | if (depth == data.depth) { 28 | double x2 = x1 - Math.sin(angle * Math.PI / 180.0) * side; 29 | double y2 = y1 - Math.cos(angle * Math.PI / 180.0) * side; 30 | g.setColor(AlgoVisHelper.Indigo); 31 | g.drawLine(x1, y1, x2, y2); 32 | return; 33 | } 34 | 35 | double s = side / 2; 36 | double x2 = x1 - Math.sin(angle * Math.PI / 180.0) * s; 37 | double y2 = y1 - Math.cos(angle * Math.PI / 180.0) * s; 38 | g.setColor(AlgoVisHelper.Indigo); 39 | g.drawLine(x1, y1, x2, y2); 40 | 41 | drawFractal(g, x2, y2, s, angle + data.splitAngle / 2, depth + 1); 42 | drawFractal(g, x2, y2, s, angle - data.splitAngle / 2, depth + 1); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/J_Fractal_Drawing/vicsek_fractal/VicsekData.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.J_Fractal_Drawing.vicsek_fractal; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: 6 | * @Date: Created in 13:52 2018/10/15 7 | */ 8 | public class VicsekData { 9 | 10 | public int depth; 11 | 12 | public VicsekData(int depth) { 13 | this.depth = depth; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/J_Fractal_Drawing/vicsek_fractal/VicsekFrame.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.J_Fractal_Drawing.vicsek_fractal; 2 | 3 | import com.cipher.algorithm_visualization.A_Base.AlgoFrame; 4 | import com.cipher.algorithm_visualization.A_Base.AlgoVisHelper; 5 | 6 | /** 7 | * @Author: CipherCui 8 | * @Description: 9 | * @Date: Created in 13:53 2018/10/15 10 | */ 11 | public class VicsekFrame extends AlgoFrame { 12 | 13 | public VicsekFrame(String title, int canvasWidth, int canvasHeight) { 14 | super(title, canvasWidth, canvasHeight); 15 | } 16 | 17 | @Override 18 | public void paint(AlgoVisHelper algoVisHelper, Object obj) { 19 | VicsekData data = (VicsekData) obj; 20 | drawFractal(algoVisHelper, 0, 0, getCanvasWidth(), getCanvasHeight(), 0); 21 | } 22 | 23 | private void drawFractal(AlgoVisHelper g, int x, int y, int w, int h, int depth) { 24 | VicsekData data = (VicsekData) getData(); 25 | if (depth == data.depth) { 26 | g.setColor(AlgoVisHelper.Indigo); 27 | g.fillRectangle(x, y, w, h); 28 | return; 29 | } 30 | if (w <= 1 || h <= 1) { 31 | g.setColor(AlgoVisHelper.Indigo); 32 | g.fillRectangle(x, y, Math.max(w, 1), Math.max(h, 1)); 33 | return; 34 | } 35 | int w_3 = w / 3; 36 | int h_3 = h / 3; 37 | drawFractal(g, x, y, w_3, h_3, depth + 1); 38 | drawFractal(g, x + 2 * w_3, y, w_3, h_3, depth + 1); 39 | drawFractal(g, x + w_3, y + h_3, w_3, h_3, depth + 1); 40 | drawFractal(g, x, y + 2 * h_3, w_3, h_3, depth + 1); 41 | drawFractal(g, x + 2 * w_3, y + 2 * h_3, w_3, h_3, depth + 1); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/J_Fractal_Drawing/vicsek_fractal/VicsekFrame2.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithm_visualization.J_Fractal_Drawing.vicsek_fractal; 2 | 3 | import com.cipher.algorithm_visualization.A_Base.AlgoFrame; 4 | import com.cipher.algorithm_visualization.A_Base.AlgoVisHelper; 5 | 6 | /** 7 | * @Author: CipherCui 8 | * @Description: 9 | * @Date: Created in 13:53 2018/10/15 10 | */ 11 | public class VicsekFrame2 extends AlgoFrame { 12 | 13 | public VicsekFrame2(String title, int canvasWidth, int canvasHeight) { 14 | super(title, canvasWidth, canvasHeight); 15 | } 16 | 17 | @Override 18 | public void paint(AlgoVisHelper algoVisHelper, Object obj) { 19 | VicsekData data = (VicsekData) obj; 20 | drawFractal(algoVisHelper, 0, 0, getCanvasWidth(), getCanvasHeight(), 0); 21 | } 22 | 23 | private void drawFractal(AlgoVisHelper g, int x, int y, int w, int h, int depth) { 24 | VicsekData data = (VicsekData) getData(); 25 | if (depth == data.depth) { 26 | g.setColor(AlgoVisHelper.Indigo); 27 | g.fillRectangle(x, y, w, h); 28 | return; 29 | } 30 | if (w <= 1 || h <= 1) { 31 | g.setColor(AlgoVisHelper.Indigo); 32 | g.fillRectangle(x, y, Math.max(w, 1), Math.max(h, 1)); 33 | return; 34 | } 35 | int w_3 = w / 3; 36 | int h_3 = h / 3; 37 | drawFractal(g, x + w_3, y, w_3, h_3, depth + 1); 38 | drawFractal(g, x, y + h_3, w_3, h_3, depth + 1); 39 | drawFractal(g, x + w_3, y + h_3, w_3, h_3, depth + 1); 40 | drawFractal(g, x + 2 * w_3, y + h_3, w_3, h_3, depth + 1); 41 | drawFractal(g, x + w_3, y + 2 * h_3, w_3, h_3, depth + 1); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithm_visualization/readme.md: -------------------------------------------------------------------------------- 1 | ## 算法应用、可视化 2 | 3 | https://github.com/liuyubobobo/Play-with-Algorithm-Visualization 4 | 5 | - 圆圈运动 6 | 7 | 圆圈的碰撞运动,预热JFrame基础; 8 | 9 | - 分钱问题 10 | 11 | 房间里有100个人,每个人有100元钱,他们在玩一个游戏。每轮游戏中, 12 | 每个人都要拿出一元钱随机给另一个人,最后这100个人的财富分布是怎样的? 13 | 14 | - 蒙特卡洛算法 15 | 16 | - 计算PI值 17 | 18 | 利用正方形的面积和圆的面积,计算pi,pi = 4 * 圆面积 / 方形面积; 19 | 20 | - 三门问题(Monty Hall problem) 21 | 22 | 参赛者会看见三扇关闭了的门,其中一扇的后面有一辆汽车,选中后面有车的那扇门就可以赢得该汽车, 23 | 而另外两扇门后面什么都没有。当参赛者选定一扇门,但开启的时候,节目主持人会开启剩下两扇门的 24 | 其中一扇,这扇门背后一定没有汽车。主持人会问参赛者要不要换另一扇门。 25 | 问题是:换另一扇门会否增加参赛者获奖概率? 26 | 27 | - 开宝箱问题 28 | 29 | 在游戏里,有一种宝箱,打开这个宝箱获得传奇武器的概率是20%,现在你打开5个这样的宝箱,获得传奇 30 | 武器的概率是多少? 31 | 32 | - 排序算法可视化 33 | 34 | - 选择排序 35 | - 插入排序 36 | - 归并排序 37 | - 快速排序 38 | - 堆排序 39 | 40 | - 走迷宫 41 | 42 | - 深度优先 43 | - 广度优先 44 | 45 | - 随机迷宫生成 46 | 47 | - 深度优先 48 | - 广度优先 49 | - 随机队列 50 | 51 | - 数组实现,入队尾,随机出队,是广度优先的随机版; 52 | - 链表实现,随机入队尾或队首,随机出队尾或队首,等于结合深度优先和广度优先; 53 | 54 | - 扫雷 55 | 56 | - 随机生成雷区 57 | - 验证算法的随机性 58 | 59 | 以扑克牌为例,54张牌,可以得到54!种结果。一个“好”的洗牌算法可以等概率的获取这54!种结果之一。 60 | 61 | - Fisher-Yates-Knuth 洗牌算法 62 | - floodfill 算法 63 | 64 | - Move the Box 自动生成解 65 | 66 | - 分形图 67 | 68 | - Recursive Circle 69 | - Vicsek Fractal 70 | - Sierpinski Carpet 71 | - Sierpinski Triangle 72 | - Snowflake Fractal 73 | - Tree Fractal -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithms/A_Sort/A_BubbleSort/BubbleSort.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithms.A_Sort.A_BubbleSort; 2 | 3 | import static com.cipher.algorithms.A_Sort.SortTestHelper.*; 4 | 5 | /** 6 | * 冒泡排序 O(n^2) 7 | * 循环 n 趟,每一趟依次比较每个元素与下一个元素的大小,把最大的元素“沉”到最后 8 | * Created by cipher on 2017/9/12. 9 | */ 10 | public class BubbleSort { 11 | 12 | public static void sort(int[] data) { 13 | // 循环 n 趟 14 | for (int i = 0; i < data.length; i++) { 15 | // 每一趟,下标从 1 开始递增,依次与前一个元素比较大小,大的交换到后面 16 | for (int j = 1; j < data.length - i; j++) { 17 | if (data[j - 1]>(data[j])) { 18 | swap(data, j - 1, j); 19 | } 20 | } 21 | } 22 | } 23 | 24 | public static void main(String[] args) { 25 | int[] data = generateRandomArray(10000, 1, 10000); 26 | // printArray(data); 27 | testSort(BubbleSort.class, data); 28 | // printArray(data); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithms/A_Sort/B_SelectionSort/SelectionSort.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithms.A_Sort.B_SelectionSort; 2 | 3 | import static com.cipher.algorithms.A_Sort.SortTestHelper.*; 4 | 5 | /** 6 | * 选择排序 O(n^2) 7 | * i 从 0 开始递增,以第 i 个元素为最小,从 i+1 开始找出比该值更小的元素,与之交换位置。 8 | * 重要性质:交换次数最少 O(n) 9 | * Created by cipher on 2017/9/14. 10 | */ 11 | public class SelectionSort { 12 | 13 | public static void sort(int[] data) { 14 | for (int i = 0; i < data.length; i++) { 15 | // 假设第 i 个元素为最小 16 | int minIndex = i; 17 | // 从 i+1 开始找出比该值更小的元素,与之交换位置。 18 | for (int j = i + 1; j < data.length; j++) { 19 | if (data[j] < (data[minIndex])) { 20 | minIndex = j; 21 | } 22 | } 23 | swap(data, i, minIndex); 24 | } 25 | } 26 | 27 | public static void main(String[] args) { 28 | int[] data = generateRandomArray(10000, 1, 10000); 29 | // printArray(data); 30 | testSort(SelectionSort.class, data); 31 | // printArray(data); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithms/A_Sort/C_InsertionSort/InsertionSort.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithms.A_Sort.C_InsertionSort; 2 | 3 | import com.cipher.algorithms.A_Sort.B_SelectionSort.SelectionSort; 4 | 5 | import static com.cipher.algorithms.A_Sort.SortTestHelper.*; 6 | 7 | /** 8 | * 插入排序 O(n^2) 9 | * 从第 1 个元素开始,依次判断此元素与之前元素的大小, 10 | * 如果比前元素小,就把前元素往后挪一个位置,否则终止循环,把该元素放到最后终止的位置 11 | * 重要性质:提前终止内层循环,在近乎有序的数组中效率最高 12 | * Created by cipher on 2017/10/12. 13 | */ 14 | public class InsertionSort { 15 | 16 | public static void sort(int[] data) { 17 | for (int i = 1; i < data.length; i++) { 18 | // 寻找元素 arr[i] 合适的插入位置 19 | int x = data[i]; 20 | // j 保存元素 x 应该插入的位置 21 | int j; 22 | for (j = i; j >= 1 && x < (data[j - 1]); j--) { 23 | data[j] = data[j - 1]; 24 | } 25 | data[j] = x; 26 | } 27 | } 28 | 29 | public static void main(String[] args) { 30 | int[] data1 = generateRandomArray(20000, 1, 100000); 31 | int[] data2 = copy(data1); 32 | testSort(InsertionSort.class, data1); 33 | testSort(SelectionSort.class, data2); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithms/A_Sort/D_ShellSort/ShellSort.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithms.A_Sort.D_ShellSort; 2 | 3 | import static com.cipher.algorithms.A_Sort.SortTestHelper.generateRandomArray; 4 | import static com.cipher.algorithms.A_Sort.SortTestHelper.testSort; 5 | 6 | /** 7 | * 希尔排序 —— 插入排序的延伸,不稳定,最差 O(n^2) 8 | * 将插入排序中的步长 1 换成一个增量序列 9 | * Created by cipher on 2017/10/12. 10 | */ 11 | public class ShellSort { 12 | 13 | public static void sort(int[] data) { 14 | // 计算增量序列: 1, 4, 13, 40, 121, 364, 1093... 15 | int h = 1; 16 | while (h < data.length / 3) { 17 | h = 3 * h + 1; 18 | } 19 | while (h >= 1) { 20 | for (int i = h; i < data.length; i++) { 21 | int x = data[i]; 22 | int j; 23 | for (j = i; j >= h && x < (data[j - h]); j = j - h) { 24 | data[j] = data[j - h]; 25 | } 26 | data[j] = x; 27 | } 28 | h /= 3; 29 | } 30 | } 31 | 32 | public static void main(String[] args) { 33 | int[] data1 = generateRandomArray(10000, 1, 10000); 34 | testSort(ShellSort.class, data1); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithms/A_Sort/F_QuickSort/QuickSort2Way.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithms.A_Sort.F_QuickSort; 2 | 3 | import static com.cipher.algorithms.A_Sort.SortTestHelper.*; 4 | 5 | /** 6 | * @Author: CipherCui 7 | * @Description: 8 | * @Date: Created in 14:13 2018/9/21 9 | */ 10 | public class QuickSort2Way { 11 | 12 | public static void sort(int[] nums) { 13 | sort(nums, 0, nums.length - 1); 14 | } 15 | 16 | private static void sort(int[] nums, int l, int r) { 17 | if (l >= r) { 18 | return; 19 | } 20 | int p = partition(nums, l, r); 21 | sort(nums, l, p - 1); 22 | sort(nums, p + 1, r); 23 | } 24 | 25 | private static int partition(int[] nums, int l, int r) { 26 | int p = (int) (Math.random() * (r - l) + 1) + l; 27 | swap(nums, p, l); 28 | int v = nums[l]; 29 | int i = l + 1; 30 | int j = r; 31 | while (true) { 32 | while (i <= r && nums[i] < v) { 33 | i++; 34 | } 35 | while (j >= l + 1 && nums[j] > v) { 36 | j--; 37 | } 38 | if (i > j) { 39 | break; 40 | } 41 | swap(nums, i, j); 42 | i++; 43 | j--; 44 | } 45 | swap(nums, l, j); 46 | return j; 47 | } 48 | 49 | public static void main(String[] args) { 50 | int[] data = generateRandomArray(10, 1, 10); 51 | printArray(data); 52 | testSort(QuickSort2Way.class, data); 53 | printArray(data); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithms/A_Sort/F_QuickSort/QuickSort3Way.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithms.A_Sort.F_QuickSort; 2 | 3 | import static com.cipher.algorithms.A_Sort.SortTestHelper.*; 4 | 5 | /** 6 | * @Author: CipherCui 7 | * @Description: 8 | * @Date: Created in 14:13 2018/9/21 9 | */ 10 | public class QuickSort3Way { 11 | 12 | public static void sort(int[] nums) { 13 | sort(nums, 0, nums.length - 1); 14 | } 15 | 16 | private static void sort(int[] nums, int l, int r) { 17 | if (l >= r) { 18 | return; 19 | } 20 | 21 | int p = (int) (Math.random() * (r - l) + 1) + l; 22 | swap(nums, l, p); 23 | int v = nums[l]; 24 | int lt = l; 25 | int gt = r + 1; 26 | int i = l + 1; 27 | while (i < gt) { 28 | if (nums[i] < v) { 29 | swap(nums, i, lt + 1); 30 | i++; 31 | lt++; 32 | } else if (nums[i] > v) { 33 | swap(nums, i, gt - 1); 34 | gt--; 35 | } else { 36 | i++; 37 | } 38 | } 39 | swap(nums, l, lt); 40 | sort(nums, l, lt - 1); 41 | sort(nums, gt, r); 42 | } 43 | 44 | public static void main(String[] args) { 45 | int[] data = generateRandomArray(10, 1, 10); 46 | printArray(data); 47 | testSort(QuickSort3Way.class, data); 48 | printArray(data); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithms/A_Sort/F_QuickSort/QuickSortRandom.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithms.A_Sort.F_QuickSort; 2 | 3 | import static com.cipher.algorithms.A_Sort.SortTestHelper.*; 4 | 5 | /** 6 | * @Author: CipherCui 7 | * @Description: 8 | * @Date: Created in 14:13 2018/9/21 9 | */ 10 | public class QuickSortRandom { 11 | 12 | public static void sort(int[] nums) { 13 | sort(nums, 0, nums.length - 1); 14 | } 15 | 16 | private static void sort(int[] nums, int l, int r) { 17 | if (l >= r) { 18 | return; 19 | } 20 | int p = partition(nums, l, r); 21 | sort(nums, l, p - 1); 22 | sort(nums, p + 1, r); 23 | } 24 | 25 | private static int partition(int[] nums, int l, int r) { 26 | int p = (int) (Math.random() * (r - l) + 1) + l; 27 | swap(nums, p, l); 28 | int v = nums[l]; 29 | int j = l; 30 | for (int i = l + 1; i <= r; i++) { 31 | if (nums[i] < v) { 32 | j++; 33 | swap(nums, i, j); 34 | } 35 | } 36 | swap(nums, l, j); 37 | return j; 38 | } 39 | 40 | public static void main(String[] args) { 41 | int[] data = generateRandomArray(10, 1, 10); 42 | printArray(data); 43 | testSort(QuickSortRandom.class, data); 44 | printArray(data); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithms/A_Sort/F_QuickSort/QuickSortSimple.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithms.A_Sort.F_QuickSort; 2 | 3 | import static com.cipher.algorithms.A_Sort.SortTestHelper.*; 4 | 5 | /** 6 | * @Author: CipherCui 7 | * @Description: 8 | * @Date: Created in 14:13 2018/9/21 9 | */ 10 | public class QuickSortSimple { 11 | 12 | public static void sort(int[] nums) { 13 | sort(nums, 0, nums.length - 1); 14 | } 15 | 16 | private static void sort(int[] nums, int l, int r) { 17 | if (l >= r) { 18 | return; 19 | } 20 | int p = partition(nums, l, r); 21 | sort(nums, l, p - 1); 22 | sort(nums, p + 1, r); 23 | } 24 | 25 | private static int partition(int[] nums, int l, int r) { 26 | int v = nums[l]; 27 | int j = l; 28 | for (int i = l + 1; i <= r; i++) { 29 | if (nums[i] < v) { 30 | j++; 31 | swap(nums, i, j); 32 | } 33 | } 34 | swap(nums, l, j); 35 | return j; 36 | } 37 | 38 | public static void main(String[] args) { 39 | int[] data = generateRandomArray(10, 1, 10); 40 | printArray(data); 41 | testSort(QuickSortSimple.class, data); 42 | printArray(data); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithms/A_Sort/TestSort.java: -------------------------------------------------------------------------------- 1 | package com.cipher.algorithms.A_Sort; 2 | 3 | import static com.cipher.algorithms.A_Sort.SortTestHelper.*; 4 | 5 | /** 6 | * Created by cipher on 2017/9/12. 7 | */ 8 | public class TestSort { 9 | 10 | public static void sort(int[] nums) { 11 | _sort(nums, 0, nums.length - 1); 12 | } 13 | 14 | private static void _sort(int[] nums, int l, int r) { 15 | if (l >= r) { 16 | return; 17 | } 18 | int p = partition(nums, l, r); 19 | _sort(nums, l, p - 1); 20 | _sort(nums, p + 1, r); 21 | } 22 | 23 | private static int partition(int[] nums, int l, int r) { 24 | int v = nums[l]; 25 | int j = l; 26 | for (int i = l + 1; i < nums.length; i++) { 27 | if (nums[i] < v) { 28 | j++; 29 | swap(nums, i, j); 30 | } 31 | } 32 | swap(nums, l, j); 33 | return j; 34 | } 35 | 36 | 37 | public static void main(String[] args) { 38 | int[] data = generateRandomArray(1000000, 1, 10); 39 | // printArray(data); 40 | testSort(TestSort.class, data); 41 | // printArray(data); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithms/A_Sort/readme.md: -------------------------------------------------------------------------------- 1 | ## 排序 2 | 3 | ### O(n^2) 4 | - 冒泡排序 5 | - 选择排序 6 | - 插入排序 7 | - 希尔排序 8 | 9 | ### O(nlogn) 10 | - 归并排序 11 | - 快速排序 -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/algorithms/readme.md: -------------------------------------------------------------------------------- 1 | ## 算法 2 | 3 | - 排序 4 | 5 | - 二分搜索树 -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/checker/Check.java: -------------------------------------------------------------------------------- 1 | package com.cipher.checker; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.Target; 6 | 7 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 8 | 9 | /** 10 | * 参数校验 注解 11 | * Created by cipher on 2017/9/20. 12 | */ 13 | @Target({ElementType.TYPE, ElementType.METHOD}) 14 | @Retention(RUNTIME) 15 | public @interface Check { 16 | 17 | // 字段校验规则,格式:字段名+校验规则+冒号+错误信息,例如:id<10:ID必须少于10 18 | String[] value(); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/checker/readme.md: -------------------------------------------------------------------------------- 1 | ## Spring 框架参数校验工具 -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/data_structure/A_Arrays/Main.java: -------------------------------------------------------------------------------- 1 | package com.cipher.data_structure.A_Arrays; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: 6 | * @Date: Created in 14:13 2018/10/22 7 | */ 8 | public class Main { 9 | 10 | public static void main(String[] args) { 11 | Array arr = new Array<>(10); 12 | for (Integer i = 0; i < 10; i++) { 13 | arr.addLast(i); 14 | } 15 | System.out.println(arr); 16 | arr.addLast(10); 17 | System.out.println(arr); 18 | arr.removeFirst(); 19 | System.out.println(arr); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/data_structure/B_Stacks_and_Queues/queue/ArrayQueue.java: -------------------------------------------------------------------------------- 1 | package com.cipher.data_structure.B_Stacks_and_Queues.queue; 2 | 3 | import com.cipher.data_structure.A_Arrays.Array; 4 | 5 | /** 6 | * @Author: CipherCui 7 | * @Description: 8 | * @Date: Created in 15:12 2018/10/23 9 | */ 10 | public class ArrayQueue implements Queue { 11 | 12 | private Array array; 13 | 14 | public ArrayQueue(int capacity) { 15 | this.array = new Array<>(capacity); 16 | } 17 | 18 | public ArrayQueue() { 19 | this(10); 20 | } 21 | 22 | @Override 23 | public int getSize() { 24 | return array.getSize(); 25 | } 26 | 27 | @Override 28 | public boolean isEmpty() { 29 | return array.isEmpty(); 30 | } 31 | 32 | @Override 33 | public void enqueue(E e) { 34 | array.addLast(e); 35 | } 36 | 37 | @Override 38 | public E dequeue() { 39 | return array.removeFirst(); 40 | } 41 | 42 | @Override 43 | public E getFront() { 44 | return array.getFirst(); 45 | } 46 | 47 | public int getCapacity() { 48 | return array.getCapacity(); 49 | } 50 | 51 | @Override 52 | public String toString() { 53 | StringBuilder res = new StringBuilder(); 54 | res.append("Queue: front ["); 55 | for (int i = 0; i < array.getSize(); i++) { 56 | res.append(array.get(i)); 57 | res.append(i == array.getSize() - 1 ? "" : ", "); 58 | } 59 | res.append("] tail"); 60 | return res.toString(); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/data_structure/B_Stacks_and_Queues/queue/Queue.java: -------------------------------------------------------------------------------- 1 | package com.cipher.data_structure.B_Stacks_and_Queues.queue; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: 6 | * @Date: Created in 15:08 2018/10/23 7 | */ 8 | public interface Queue { 9 | 10 | int getSize(); 11 | 12 | boolean isEmpty(); 13 | 14 | void enqueue(E e); 15 | 16 | E dequeue(); 17 | 18 | E getFront(); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/data_structure/B_Stacks_and_Queues/queue/TestQueue.java: -------------------------------------------------------------------------------- 1 | package com.cipher.data_structure.B_Stacks_and_Queues.queue; 2 | 3 | import com.cipher.data_structure.C_Linked_List.LinkedListQueue; 4 | 5 | import java.util.Random; 6 | 7 | /** 8 | * @Author: CipherCui 9 | * @Description: 10 | * @Date: Created in 16:35 2018/10/23 11 | */ 12 | public class TestQueue { 13 | 14 | private static double testQueue(Queue q, int opCount) { 15 | long start = System.nanoTime(); 16 | Random random = new Random(); 17 | for (int i = 0; i < opCount; i++) { 18 | q.enqueue(random.nextInt(Integer.MAX_VALUE)); 19 | } 20 | for (int i = 0; i < opCount; i++) { 21 | q.dequeue(); 22 | } 23 | long end = System.nanoTime(); 24 | return (end - start) / 1000000000.0; 25 | } 26 | 27 | public static void main(String[] args) { 28 | int opCount = 100000; 29 | System.out.println(testQueue(new ArrayQueue<>(), opCount)); 30 | System.out.println(testQueue(new LoopQueue<>(), opCount)); 31 | System.out.println(testQueue(new LinkedListQueue<>(), opCount)); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/data_structure/B_Stacks_and_Queues/stack/ArrayStack.java: -------------------------------------------------------------------------------- 1 | package com.cipher.data_structure.B_Stacks_and_Queues.stack; 2 | 3 | import com.cipher.data_structure.A_Arrays.Array; 4 | 5 | /** 6 | * @Author: CipherCui 7 | * @Description: 8 | * @Date: Created in 13:50 2018/10/23 9 | */ 10 | public class ArrayStack implements Stack { 11 | 12 | private Array array; 13 | 14 | public ArrayStack(int capacity) { 15 | array = new Array<>(capacity); 16 | } 17 | 18 | public ArrayStack() { 19 | this(10); 20 | } 21 | 22 | public int getCapacity() { 23 | return array.getCapacity(); 24 | } 25 | 26 | @Override 27 | public void push(E e) { 28 | array.addLast(e); 29 | } 30 | 31 | @Override 32 | public E pop() { 33 | return array.removeLast(); 34 | } 35 | 36 | @Override 37 | public E peek() { 38 | return array.getLast(); 39 | } 40 | 41 | @Override 42 | public int getSize() { 43 | return array.getSize(); 44 | } 45 | 46 | @Override 47 | public boolean isEmpty() { 48 | return array.isEmpty(); 49 | } 50 | 51 | @Override 52 | public String toString() { 53 | StringBuilder res = new StringBuilder(); 54 | res.append("Stack: "); 55 | res.append('['); 56 | for (int i = 0; i < array.getSize(); i++) { 57 | res.append(array.get(i)); 58 | res.append(i == array.getSize() - 1 ? "" : ", "); 59 | } 60 | res.append("] top"); 61 | return res.toString(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/data_structure/B_Stacks_and_Queues/stack/Stack.java: -------------------------------------------------------------------------------- 1 | package com.cipher.data_structure.B_Stacks_and_Queues.stack; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: 6 | * @Date: Created in 13:53 2018/10/23 7 | */ 8 | public interface Stack { 9 | 10 | void push(E e); 11 | 12 | E pop(); 13 | 14 | E peek(); 15 | 16 | int getSize(); 17 | 18 | boolean isEmpty(); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/data_structure/B_Stacks_and_Queues/stack/ValidParentheses.java: -------------------------------------------------------------------------------- 1 | package com.cipher.data_structure.B_Stacks_and_Queues.stack; 2 | 3 | /** 4 | * 给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。 5 | *

6 | * 有效字符串需满足: 7 | *

8 | * 左括号必须用相同类型的右括号闭合。 9 | * 左括号必须以正确的顺序闭合。 10 | * 注意空字符串可被认为是有效字符串。 11 | */ 12 | public class ValidParentheses { 13 | 14 | public static boolean isValid(String s) { 15 | Stack stack = new ArrayStack<>(); 16 | for (int i = 0; i < s.length(); i++) { 17 | char c = s.charAt(i); 18 | if (c == '(' || c == '{' || c == '[') { 19 | stack.push(c); 20 | } else { 21 | if (stack.isEmpty()) { 22 | return false; 23 | } 24 | char topChar = stack.pop(); 25 | if (c == ')' && topChar != '(') { 26 | return false; 27 | } 28 | if (c == '}' && topChar != '{') { 29 | return false; 30 | } 31 | if (c == ']' && topChar != '[') { 32 | return false; 33 | } 34 | } 35 | } 36 | return stack.isEmpty(); 37 | } 38 | 39 | public static void main(String[] args) { 40 | System.out.println(isValid("()")); 41 | System.out.println(isValid("()[]{}")); 42 | System.out.println(isValid("(]")); 43 | System.out.println(isValid("([)]")); 44 | System.out.println(isValid("{[]}")); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/data_structure/C_Linked_List/LinkedListStack.java: -------------------------------------------------------------------------------- 1 | package com.cipher.data_structure.C_Linked_List; 2 | 3 | import com.cipher.data_structure.B_Stacks_and_Queues.stack.Stack; 4 | 5 | /** 6 | * @Author: CipherCui 7 | * @Description: 8 | * @Date: Created in 14:26 2018/10/24 9 | */ 10 | public class LinkedListStack implements Stack { 11 | 12 | private LinkedList list; 13 | 14 | public LinkedListStack() { 15 | this.list = new LinkedList<>(); 16 | } 17 | 18 | @Override 19 | public void push(E e) { 20 | list.addFirst(e); 21 | } 22 | 23 | @Override 24 | public E pop() { 25 | return list.removeFirst(); 26 | } 27 | 28 | @Override 29 | public E peek() { 30 | return list.getFirst(); 31 | } 32 | 33 | @Override 34 | public int getSize() { 35 | return list.getSize(); 36 | } 37 | 38 | @Override 39 | public boolean isEmpty() { 40 | return list.isEmpty(); 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | StringBuilder res = new StringBuilder(); 46 | res.append("Stack: top "); 47 | res.append(list); 48 | return res.toString(); 49 | } 50 | 51 | public static void main(String[] args) { 52 | LinkedListStack stack = new LinkedListStack<>(); 53 | for(int i = 0 ; i < 5 ; i ++){ 54 | stack.push(i); 55 | System.out.println(stack); 56 | } 57 | stack.pop(); 58 | System.out.println(stack); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/data_structure/C_Linked_List/Main.java: -------------------------------------------------------------------------------- 1 | package com.cipher.data_structure.C_Linked_List; 2 | 3 | import com.cipher.data_structure.B_Stacks_and_Queues.stack.ArrayStack; 4 | import com.cipher.data_structure.B_Stacks_and_Queues.stack.Stack; 5 | 6 | import java.util.Random; 7 | 8 | /** 9 | * @Author: CipherCui 10 | * @Description: 11 | * @Date: Created in 14:13 2018/10/22 12 | */ 13 | public class Main { 14 | 15 | private static double testStack(Stack q, int opCount) { 16 | long start = System.nanoTime(); 17 | Random random = new Random(); 18 | for (int i = 0; i < opCount; i++) { 19 | q.push(random.nextInt(Integer.MAX_VALUE)); 20 | } 21 | for (int i = 0; i < opCount; i++) { 22 | q.pop(); 23 | } 24 | long end = System.nanoTime(); 25 | return (end - start) / 1000000000.0; 26 | } 27 | 28 | public static void main(String[] args) { 29 | int opCount = 100000; 30 | System.out.println(testStack(new ArrayStack<>(), opCount)); 31 | System.out.println(testStack(new LinkedListStack<>(), opCount)); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/data_structure/D_ListNode_and_Recursion/LeetCode203.java: -------------------------------------------------------------------------------- 1 | package com.cipher.data_structure.D_ListNode_and_Recursion; 2 | 3 | /** 4 | * 删除链表中等于给定值 val 的所有节点。 5 | *

6 | * 示例: 7 | *

8 | * 输入: 1->2->6->3->4->5->6, val = 6 9 | * 输出: 1->2->3->4->5 10 | */ 11 | public class LeetCode203 { 12 | 13 | public ListNode removeElements(ListNode head, int val) { 14 | while (head != null && head.val == val) { 15 | ListNode delNode = head; 16 | head = head.next; 17 | delNode.next = null; 18 | } 19 | if (head == null) { 20 | return null; 21 | } 22 | ListNode prev = head; 23 | while (prev.next != null) { 24 | if (prev.next.val == val) { 25 | ListNode delNode = prev.next; 26 | prev.next = delNode.next; 27 | delNode.next = null; 28 | } else { 29 | prev = prev.next; 30 | } 31 | } 32 | return head; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/data_structure/D_ListNode_and_Recursion/LeetCode203_2.java: -------------------------------------------------------------------------------- 1 | package com.cipher.data_structure.D_ListNode_and_Recursion; 2 | 3 | /** 4 | * 删除链表中等于给定值 val 的所有节点。 5 | *

6 | * 示例: 7 | *

8 | * 输入: 1->2->6->3->4->5->6, val = 6 9 | * 输出: 1->2->3->4->5 10 | */ 11 | public class LeetCode203_2 { 12 | 13 | public static ListNode removeElements(ListNode head, int val) { 14 | ListNode dummyHead = new ListNode(-1); 15 | dummyHead.next = head; 16 | ListNode prev = dummyHead; 17 | while (prev.next != null) { 18 | if (prev.next.val == val) { 19 | prev.next = prev.next.next; 20 | } else { 21 | prev = prev.next; 22 | } 23 | } 24 | return dummyHead.next; 25 | } 26 | 27 | public static void main(String[] args) { 28 | ListNode head = new ListNode(new int[]{1, 2, 6, 3, 4, 5, 6}); 29 | System.out.println(head); 30 | ListNode result = removeElements(head, 6); 31 | System.out.println(result); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/data_structure/D_ListNode_and_Recursion/LeetCode203_3.java: -------------------------------------------------------------------------------- 1 | package com.cipher.data_structure.D_ListNode_and_Recursion; 2 | 3 | /** 4 | * 删除链表中等于给定值 val 的所有节点。 5 | *

6 | * 示例: 7 | *

8 | * 输入: 1->2->6->3->4->5->6, val = 6 9 | * 输出: 1->2->3->4->5 10 | */ 11 | public class LeetCode203_3 { 12 | 13 | public static ListNode removeElements(ListNode head, int val) { 14 | if (head == null) { 15 | return null; 16 | } 17 | head.next = removeElements(head.next, val); 18 | return head.val == val ? head.next : head; 19 | } 20 | 21 | public static void main(String[] args) { 22 | ListNode head = new ListNode(new int[]{1, 2, 6, 3, 4, 5, 6}); 23 | System.out.println(head); 24 | ListNode result = removeElements(head, 6); 25 | System.out.println(result); 26 | } 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/data_structure/D_ListNode_and_Recursion/LeetCode203_4.java: -------------------------------------------------------------------------------- 1 | package com.cipher.data_structure.D_ListNode_and_Recursion; 2 | 3 | /** 4 | * 删除链表中等于给定值 val 的所有节点。 5 | *

6 | * 示例: 7 | *

8 | * 输入: 1->2->6->3->4->5->6, val = 6 9 | * 输出: 1->2->3->4->5 10 | */ 11 | public class LeetCode203_4 { 12 | 13 | public static ListNode removeElements(ListNode head, int val, int depth) { 14 | String depthString = generateDepthString(depth); 15 | System.out.print(depthString); 16 | System.out.println("Call: remove " + val + " in " + head); 17 | if (head == null) { 18 | System.out.print(depthString); 19 | System.out.println("Return: " + head); 20 | return null; 21 | } 22 | ListNode res = removeElements(head.next, val, depth + 1); 23 | System.out.print(depthString); 24 | System.out.println("After remove " + val + ": " + res); 25 | ListNode ret; 26 | if (head.val == val) { 27 | ret = res; 28 | } else { 29 | head.next = res; 30 | ret = head; 31 | } 32 | System.out.print(depthString); 33 | System.out.println("Return: " + ret); 34 | return ret; 35 | } 36 | 37 | private static String generateDepthString(int depth) { 38 | StringBuilder res = new StringBuilder(); 39 | for (int i = 0; i < depth; i++) { 40 | res.append("--"); 41 | } 42 | return res.toString(); 43 | } 44 | 45 | public static void main(String[] args) { 46 | ListNode head = new ListNode(new int[]{1, 2, 6, 3, 4, 5, 6}); 47 | System.out.println(head); 48 | ListNode result = removeElements(head, 6, 0); 49 | System.out.println(result); 50 | } 51 | 52 | 53 | } 54 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/data_structure/D_ListNode_and_Recursion/ListNode.java: -------------------------------------------------------------------------------- 1 | package com.cipher.data_structure.D_ListNode_and_Recursion; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: 6 | * @Date: Created in 10:10 2018/10/25 7 | */ 8 | public class ListNode { 9 | 10 | public int val; 11 | public ListNode next; 12 | 13 | public ListNode(int x) { 14 | val = x; 15 | } 16 | 17 | public ListNode(int[] arr) { 18 | this.val = arr[0]; 19 | ListNode cur = this; 20 | for (int i = 1; i < arr.length; i++) { 21 | cur.next = new ListNode(arr[i]); 22 | cur = cur.next; 23 | } 24 | } 25 | 26 | @Override 27 | public String toString() { 28 | StringBuilder res = new StringBuilder(); 29 | res.append("HEAD "); 30 | ListNode cur = this; 31 | while (cur != null) { 32 | res.append(cur.val).append(" -> "); 33 | cur = cur.next; 34 | } 35 | res.append("NULL"); 36 | return res.toString(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/data_structure/D_ListNode_and_Recursion/Sum.java: -------------------------------------------------------------------------------- 1 | package com.cipher.data_structure.D_ListNode_and_Recursion; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: 6 | * @Date: Created in 17:30 2018/10/25 7 | */ 8 | public class Sum { 9 | 10 | public static int sum(int[] arr) { 11 | return sum(arr, 0); 12 | } 13 | 14 | private static int sum(int[] arr, int l) { 15 | if (l == arr.length) { 16 | return 0; 17 | } 18 | return arr[l] + sum(arr, l + 1); 19 | } 20 | 21 | public static void main(String[] args) { 22 | int[] arr = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 23 | int sum = sum(arr); 24 | System.out.println(sum); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/data_structure/F_Set_and_Map/map/LeetCode349.java: -------------------------------------------------------------------------------- 1 | package com.cipher.data_structure.F_Set_and_Map.map; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * 给定两个数组,编写一个函数来计算它们的交集。 7 | *

8 | * 示例 1: 9 | *

10 | * 输入: nums1 = [1,2,2,1], nums2 = [2,2] 11 | * 输出: [2] 12 | * 示例 2: 13 | *

14 | * 输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4] 15 | * 输出: [9,4] 16 | * 说明: 17 | *

18 | * 输出结果中的每个元素一定是唯一的。 19 | * 我们可以不考虑输出结果的顺序。 20 | */ 21 | public class LeetCode349 { 22 | 23 | public int[] intersection(int[] nums1, int[] nums2) { 24 | Set set = new TreeSet<>(); 25 | for (int num : nums1) { 26 | set.add(num); 27 | } 28 | List list = new ArrayList<>(); 29 | for (int num : nums2) { 30 | if (set.contains(num)) { 31 | list.add(num); 32 | set.remove(num); 33 | } 34 | } 35 | int[] res = new int[list.size()]; 36 | for (int i = 0; i < list.size(); i++) { 37 | res[i] = list.get(i); 38 | } 39 | return res; 40 | } 41 | 42 | public static void main(String[] args) { 43 | LeetCode349 leetCode = new LeetCode349(); 44 | int[] intersection = leetCode.intersection(new int[]{1, 2, 2, 1}, new int[]{2, 2}); 45 | System.out.println(Arrays.toString(intersection)); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/data_structure/F_Set_and_Map/map/Main.java: -------------------------------------------------------------------------------- 1 | package com.cipher.data_structure.F_Set_and_Map.map; 2 | 3 | import com.cipher.data_structure.F_Set_and_Map.FileOperation; 4 | 5 | import java.util.ArrayList; 6 | 7 | import static java.lang.System.nanoTime; 8 | 9 | /** 10 | * @Author: CipherCui 11 | * @Description: 12 | * @Date: Created in 10:55 2018/10/31 13 | */ 14 | public class Main { 15 | 16 | private static final String PATH = "src/main/java/com/cipher/data_structure/F_Set_And_Map/resource/"; 17 | private static final String A_TALE_OF_TWO_CITIES = PATH + "a-tale-of-two-cities.txt"; 18 | private static final String PRIDE_AND_PREJUDICE = PATH + "pride-and-prejudice.txt"; 19 | 20 | public static void main(String[] args) { 21 | ArrayList words = new ArrayList<>(); 22 | FileOperation.readFile(PRIDE_AND_PREJUDICE, words); 23 | System.out.println("Total words: " + words.size()); 24 | System.out.println("----------------------------"); 25 | 26 | testMap(new LinkedListMap<>(), words); 27 | System.out.println(); 28 | testMap(new BSTMap<>(), words); 29 | } 30 | 31 | private static void testMap(Map map, ArrayList words) { 32 | long start = nanoTime(); 33 | for (String w : words) { 34 | if (map.contains(w)) { 35 | map.set(w, map.get(w) + 1); 36 | } else { 37 | map.add(w, 1); 38 | } 39 | } 40 | long end = nanoTime(); 41 | System.out.println("Frequency of PRIDE: " + map.get("pride")); 42 | System.out.println("Total different words: " + map.getSize() + " during " + (end - start) / 1000000000.0); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/data_structure/F_Set_and_Map/map/Map.java: -------------------------------------------------------------------------------- 1 | package com.cipher.data_structure.F_Set_and_Map.map; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: 6 | * @Date: Created in 17:01 2018/11/7 7 | */ 8 | public interface Map { 9 | 10 | void add(K key, V value); 11 | 12 | V remove(K key); 13 | 14 | boolean contains(K key); 15 | 16 | V get(K key); 17 | 18 | void set(K key, V value); 19 | 20 | int getSize(); 21 | 22 | boolean isEmpty(); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/data_structure/F_Set_and_Map/set/BSTSet.java: -------------------------------------------------------------------------------- 1 | package com.cipher.data_structure.F_Set_and_Map.set; 2 | 3 | import com.cipher.data_structure.E_Binary_Search_Tree.BST; 4 | 5 | /** 6 | * @Author: CipherCui 7 | * @Description: 8 | * @Date: Created in 10:53 2018/10/31 9 | */ 10 | public class BSTSet implements Set { 11 | 12 | private BST bst; 13 | 14 | public BSTSet() { 15 | this.bst = new BST<>(); 16 | } 17 | 18 | @Override 19 | public void add(E e) { 20 | bst.add(e); 21 | } 22 | 23 | @Override 24 | public void remove(E e) { 25 | bst.remove(e); 26 | } 27 | 28 | @Override 29 | public boolean contains(E e) { 30 | return bst.contains(e); 31 | } 32 | 33 | @Override 34 | public int getSize() { 35 | return bst.getSize(); 36 | } 37 | 38 | @Override 39 | public boolean isEmpty() { 40 | return bst.isEmpty(); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/data_structure/F_Set_and_Map/set/LinkedListSet.java: -------------------------------------------------------------------------------- 1 | package com.cipher.data_structure.F_Set_and_Map.set; 2 | 3 | import com.cipher.data_structure.C_Linked_List.LinkedList; 4 | 5 | /** 6 | * @Author: CipherCui 7 | * @Description: 8 | * @Date: Created in 16:42 2018/10/31 9 | */ 10 | public class LinkedListSet implements Set { 11 | 12 | private LinkedList list; 13 | 14 | public LinkedListSet() { 15 | this.list = new LinkedList<>(); 16 | } 17 | 18 | @Override 19 | public void add(E e) { 20 | if (!list.contains(e)) { 21 | list.addFirst(e); 22 | } 23 | } 24 | 25 | @Override 26 | public void remove(E e) { 27 | list.removeElement(e); 28 | } 29 | 30 | @Override 31 | public boolean contains(E e) { 32 | return list.contains(e); 33 | } 34 | 35 | @Override 36 | public int getSize() { 37 | return list.getSize(); 38 | } 39 | 40 | @Override 41 | public boolean isEmpty() { 42 | return list.isEmpty(); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/data_structure/F_Set_and_Map/set/Main.java: -------------------------------------------------------------------------------- 1 | package com.cipher.data_structure.F_Set_and_Map.set; 2 | 3 | import com.cipher.data_structure.F_Set_and_Map.FileOperation; 4 | 5 | import java.util.ArrayList; 6 | 7 | import static java.lang.System.nanoTime; 8 | 9 | /** 10 | * @Author: CipherCui 11 | * @Description: 12 | * @Date: Created in 10:55 2018/10/31 13 | */ 14 | public class Main { 15 | 16 | private static final String PATH = "src/main/java/com/cipher/data_structure/F_Set_And_Map/resource/"; 17 | private static final String A_TALE_OF_TWO_CITIES = PATH + "a-tale-of-two-cities.txt"; 18 | private static final String PRIDE_AND_PREJUDICE = PATH + "pride-and-prejudice.txt"; 19 | 20 | public static void main(String[] args) { 21 | ArrayList words = new ArrayList<>(); 22 | FileOperation.readFile(PRIDE_AND_PREJUDICE, words); 23 | System.out.println("Total words: " + words.size()); 24 | 25 | testSet(new BSTSet<>(), words); 26 | testSet(new LinkedListSet<>(), words); 27 | } 28 | 29 | private static void testSet(Set set, ArrayList words) { 30 | long start = nanoTime(); 31 | for (String w : words) { 32 | set.add(w); 33 | } 34 | long end = nanoTime(); 35 | System.out.println("Total different words: " + set.getSize() + " during " + (end - start)/1000000000.0); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/data_structure/F_Set_and_Map/set/Set.java: -------------------------------------------------------------------------------- 1 | package com.cipher.data_structure.F_Set_and_Map.set; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: 6 | * @Date: Created in 10:49 2018/10/31 7 | */ 8 | public interface Set { 9 | 10 | void add(E e); 11 | 12 | void remove(E e); 13 | 14 | boolean contains(E e); 15 | 16 | int getSize(); 17 | 18 | boolean isEmpty(); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/data_structure/G_Heap_and_Priority_Queue/LeetCode347.java: -------------------------------------------------------------------------------- 1 | package com.cipher.data_structure.G_Heap_and_Priority_Queue; 2 | 3 | import java.util.*; 4 | import java.util.PriorityQueue; 5 | 6 | /** 7 | * 给定一个非空的整数数组,返回其中出现频率前 k 高的元素。 8 | *

9 | * 示例 1: 10 | *

11 | * 输入: nums = [1,1,1,2,2,3], k = 2 12 | * 输出: [1,2] 13 | * 示例 2: 14 | *

15 | * 输入: nums = [1], k = 1 16 | * 输出: [1] 17 | * 说明: 18 | *

19 | * 你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。 20 | * 你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。 21 | */ 22 | public class LeetCode347 { 23 | 24 | public List topKFrequent(int[] nums, int k) { 25 | TreeMap map = new TreeMap<>(); 26 | for (int num : nums) { 27 | if (map.containsKey(num)) { 28 | map.put(num, map.get(num) + 1); 29 | } else { 30 | map.put(num, 1); 31 | } 32 | } 33 | PriorityQueue pq = new PriorityQueue<>((a, b) -> map.get(a) - map.get(b)); 34 | for (int key : map.keySet()) { 35 | if (pq.size() < k) { 36 | pq.add(key); 37 | } else if (map.get(key) > map.get(pq.peek())) { 38 | pq.poll(); 39 | pq.add(key); 40 | } 41 | } 42 | List list = new LinkedList<>(); 43 | while (!pq.isEmpty()) { 44 | list.add(pq.poll()); 45 | } 46 | return list; 47 | } 48 | 49 | 50 | public static void main(String[] args) { 51 | LeetCode347 leetCode = new LeetCode347(); 52 | List integers = leetCode.topKFrequent(new int[]{4, 1, -1, 2, -1, 2, 3}, 2); 53 | System.out.println(integers); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/data_structure/G_Heap_and_Priority_Queue/PriorityQueue.java: -------------------------------------------------------------------------------- 1 | package com.cipher.data_structure.G_Heap_and_Priority_Queue; 2 | 3 | import com.cipher.data_structure.B_Stacks_and_Queues.queue.Queue; 4 | 5 | /** 6 | * @Author: CipherCui 7 | * @Description: 8 | * @Date: Created in 10:37 2018/11/15 9 | */ 10 | public class PriorityQueue implements Queue { 11 | 12 | private MaxHeap maxHeap; 13 | 14 | public PriorityQueue() { 15 | maxHeap = new MaxHeap<>(); 16 | } 17 | 18 | @Override 19 | public int getSize() { 20 | return maxHeap.getSize(); 21 | } 22 | 23 | @Override 24 | public boolean isEmpty() { 25 | return maxHeap.isEmpty(); 26 | } 27 | 28 | @Override 29 | public void enqueue(E e) { 30 | maxHeap.add(e); 31 | } 32 | 33 | @Override 34 | public E dequeue() { 35 | return maxHeap.extractMax(); 36 | } 37 | 38 | @Override 39 | public E getFront() { 40 | return maxHeap.findMax(); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/data_structure/readme.md: -------------------------------------------------------------------------------- 1 | ## 数据结构 2 | 3 | https://github.com/liuyubobobo/Play-with-Data-Structures 4 | 5 | - 数组 6 | 7 | - 栈和队列 8 | 9 | - 链表 10 | 11 | - 链表和递归 12 | 13 | - 二分搜索树 14 | 15 | - 集合和映射 16 | 17 | - 优先队列和堆 -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/handler_demo/handler/AbstractHandler.java: -------------------------------------------------------------------------------- 1 | package com.cipher.handler_demo.handler; 2 | 3 | import com.cipher.handler_demo.model.OrderDTO; 4 | 5 | /** 6 | * @Author: CipherCui 7 | * @Description: 8 | * @Date: Created in 13:57 2019/2/1 9 | */ 10 | public abstract class AbstractHandler { 11 | 12 | abstract public String handle(OrderDTO dto); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/handler_demo/handler/HandlerContext.java: -------------------------------------------------------------------------------- 1 | package com.cipher.handler_demo.handler; 2 | 3 | import com.cipher.handler_demo.util.BeanTool; 4 | 5 | import java.util.Map; 6 | 7 | /** 8 | * @Author: CipherCui 9 | * @Description: 处理器上下文,根据类型获取相应的处理器 10 | * @Date: Created in 10:07 2019/2/2 11 | */ 12 | @SuppressWarnings("unchecked") 13 | public class HandlerContext { 14 | 15 | private Map handlerMap; 16 | 17 | public HandlerContext(Map handlerMap) { 18 | this.handlerMap = handlerMap; 19 | } 20 | 21 | public AbstractHandler getInstance(String type) { 22 | Class clazz = handlerMap.get(type); 23 | if (clazz == null) { 24 | throw new IllegalArgumentException("not found handler for type: " + type); 25 | } 26 | return (AbstractHandler) BeanTool.getBean(clazz); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/handler_demo/handler/HandlerProcessor.java: -------------------------------------------------------------------------------- 1 | package com.cipher.handler_demo.handler; 2 | 3 | import com.cipher.handler_demo.util.ClassScaner; 4 | import com.google.common.collect.Maps; 5 | import org.springframework.beans.BeansException; 6 | import org.springframework.beans.factory.config.BeanFactoryPostProcessor; 7 | import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 8 | import org.springframework.stereotype.Component; 9 | 10 | import java.util.Map; 11 | 12 | /** 13 | * @Author: CipherCui 14 | * @Description: 15 | * @Date: Created in 14:40 2019/2/1 16 | */ 17 | @Component 18 | @SuppressWarnings("unchecked") 19 | public class HandlerProcessor implements BeanFactoryPostProcessor { 20 | 21 | private static final String HANDLER_PACKAGE = "com.cipher.handler_demo.handler.biz"; 22 | 23 | /** 24 | * 扫描@HandlerType,初始化HandlerContext,将其注册到spring容器 25 | * 26 | * @param beanFactory bean工厂 27 | * @see HandlerType 28 | * @see HandlerContext 29 | */ 30 | @Override 31 | public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { 32 | Map handlerMap = Maps.newHashMapWithExpectedSize(3); 33 | ClassScaner.scan(HANDLER_PACKAGE, HandlerType.class).forEach(clazz -> { 34 | String type = clazz.getAnnotation(HandlerType.class).value(); 35 | handlerMap.put(type, clazz); 36 | }); 37 | HandlerContext context = new HandlerContext(handlerMap); 38 | beanFactory.registerSingleton(HandlerContext.class.getName(), context); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/handler_demo/handler/HandlerType.java: -------------------------------------------------------------------------------- 1 | package com.cipher.handler_demo.handler; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * @Author: CipherCui 7 | * @Description: 8 | * @Date: Created in 10:07 2019/2/2 9 | */ 10 | @Target({ElementType.TYPE}) 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Documented 13 | @Inherited 14 | public @interface HandlerType { 15 | 16 | String value(); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/handler_demo/handler/biz/GroupHandler.java: -------------------------------------------------------------------------------- 1 | package com.cipher.handler_demo.handler.biz; 2 | 3 | import com.cipher.handler_demo.handler.AbstractHandler; 4 | import com.cipher.handler_demo.handler.HandlerType; 5 | import com.cipher.handler_demo.model.OrderDTO; 6 | import org.springframework.stereotype.Component; 7 | 8 | /** 9 | * @Author: CipherCui 10 | * @Description: 团购订单处理器 11 | * @Date: Created in 10:17 2019/2/2 12 | */ 13 | @Component 14 | @HandlerType("2") 15 | public class GroupHandler extends AbstractHandler { 16 | 17 | @Override 18 | public String handle(OrderDTO dto) { 19 | return "处理团购订单"; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/handler_demo/handler/biz/NormalHandler.java: -------------------------------------------------------------------------------- 1 | package com.cipher.handler_demo.handler.biz; 2 | 3 | import com.cipher.handler_demo.handler.AbstractHandler; 4 | import com.cipher.handler_demo.handler.HandlerType; 5 | import com.cipher.handler_demo.model.OrderDTO; 6 | import org.springframework.stereotype.Component; 7 | 8 | /** 9 | * @Author: CipherCui 10 | * @Description: 普通订单处理器 11 | * @Date: Created in 10:17 2019/2/2 12 | */ 13 | @Component 14 | @HandlerType("1") 15 | public class NormalHandler extends AbstractHandler { 16 | 17 | @Override 18 | public String handle(OrderDTO dto) { 19 | return "处理普通订单"; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/handler_demo/handler/biz/PromotionHandler.java: -------------------------------------------------------------------------------- 1 | package com.cipher.handler_demo.handler.biz; 2 | 3 | import com.cipher.handler_demo.handler.AbstractHandler; 4 | import com.cipher.handler_demo.handler.HandlerType; 5 | import com.cipher.handler_demo.model.OrderDTO; 6 | import org.springframework.stereotype.Component; 7 | 8 | /** 9 | * @Author: CipherCui 10 | * @Description: 促销订单处理器 11 | * @Date: Created in 10:17 2019/2/2 12 | */ 13 | @Component 14 | @HandlerType("3") 15 | public class PromotionHandler extends AbstractHandler { 16 | 17 | @Override 18 | public String handle(OrderDTO dto) { 19 | return "处理促销订单"; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/handler_demo/model/OrderDTO.java: -------------------------------------------------------------------------------- 1 | package com.cipher.handler_demo.model; 2 | 3 | import java.math.BigDecimal; 4 | 5 | /** 6 | * @Author: CipherCui 7 | * @Description: 8 | * @Date: Created in 9:48 2019/2/2 9 | */ 10 | public class OrderDTO { 11 | 12 | private String code; 13 | 14 | private BigDecimal price; 15 | 16 | /** 17 | * 订单类型 18 | * 1:普通订单; 19 | * 2:团购订单; 20 | * 3:促销订单; 21 | */ 22 | private String type; 23 | 24 | public String getCode() { 25 | return code; 26 | } 27 | 28 | public void setCode(String code) { 29 | this.code = code; 30 | } 31 | 32 | public BigDecimal getPrice() { 33 | return price; 34 | } 35 | 36 | public void setPrice(BigDecimal price) { 37 | this.price = price; 38 | } 39 | 40 | public String getType() { 41 | return type; 42 | } 43 | 44 | public void setType(String type) { 45 | this.type = type; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/handler_demo/service/IOrderService.java: -------------------------------------------------------------------------------- 1 | package com.cipher.handler_demo.service; 2 | 3 | import com.cipher.handler_demo.model.OrderDTO; 4 | 5 | /** 6 | * @Author: CipherCui 7 | * @Description: 8 | * @Date: Created in 9:51 2019/2/2 9 | */ 10 | public interface IOrderService { 11 | 12 | /** 13 | * 根据订单的不同类型作出不同的处理 14 | * 15 | * @param dto 订单实体 16 | * @return 为了简单,返回字符串 17 | */ 18 | String handle(OrderDTO dto); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/handler_demo/service/impl/OrderServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.cipher.handler_demo.service.impl; 2 | 3 | import com.cipher.handler_demo.model.OrderDTO; 4 | import com.cipher.handler_demo.service.IOrderService; 5 | import org.springframework.stereotype.Service; 6 | 7 | /** 8 | * @Author: CipherCui 9 | * @Description: 10 | * @Date: Created in 9:54 2019/2/2 11 | */ 12 | @Service 13 | public class OrderServiceImpl implements IOrderService { 14 | 15 | @Override 16 | public String handle(OrderDTO dto) { 17 | String type = dto.getType(); 18 | if ("1".equals(type)) { 19 | return "处理普通订单"; 20 | } else if ("2".equals(type)) { 21 | return "处理团购订单"; 22 | } else if ("3".equals(type)) { 23 | return "处理促销订单"; 24 | } 25 | return null; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/handler_demo/service/impl/OrderServiceV2Impl.java: -------------------------------------------------------------------------------- 1 | package com.cipher.handler_demo.service.impl; 2 | 3 | import com.cipher.handler_demo.handler.AbstractHandler; 4 | import com.cipher.handler_demo.handler.HandlerContext; 5 | import com.cipher.handler_demo.model.OrderDTO; 6 | import com.cipher.handler_demo.service.IOrderService; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Service; 9 | 10 | /** 11 | * @Author: CipherCui 12 | * @Description: 13 | * @Date: Created in 9:54 2019/2/2 14 | */ 15 | @Service 16 | public class OrderServiceV2Impl implements IOrderService { 17 | 18 | @Autowired 19 | private HandlerContext handlerContext; 20 | 21 | @Override 22 | public String handle(OrderDTO dto) { 23 | AbstractHandler handler = handlerContext.getInstance(dto.getType()); 24 | return handler.handle(dto); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/handler_demo/util/BeanTool.java: -------------------------------------------------------------------------------- 1 | package com.cipher.handler_demo.util; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.context.ApplicationContext; 5 | import org.springframework.context.ApplicationContextAware; 6 | import org.springframework.stereotype.Component; 7 | 8 | /** 9 | * Bean工具类
10 | * 在非spring管理的类中获取spring注册的bean 11 | * 12 | * @author cipher 13 | */ 14 | @Component 15 | public class BeanTool implements ApplicationContextAware { 16 | 17 | private static ApplicationContext applicationContext; 18 | 19 | @Override 20 | public void setApplicationContext(ApplicationContext context) throws BeansException { 21 | if (applicationContext == null) { 22 | applicationContext = context; 23 | } 24 | } 25 | 26 | public static Object getBean(String name) { 27 | return applicationContext.getBean(name); 28 | } 29 | 30 | public static T getBean(Class clazz) { 31 | return applicationContext.getBean(clazz); 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/interview/annotation/Aspect.java: -------------------------------------------------------------------------------- 1 | package com.cipher.interview.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author cipher 10 | */ 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Target(ElementType.TYPE) 13 | public @interface Aspect { 14 | 15 | Class type(); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/interview/annotation/IAspect.java: -------------------------------------------------------------------------------- 1 | package com.cipher.interview.annotation; 2 | 3 | /** 4 | * @author cipher 5 | */ 6 | public interface IAspect { 7 | 8 | void before(); 9 | void after(); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/interview/annotation/IOrder.java: -------------------------------------------------------------------------------- 1 | package com.cipher.interview.annotation; 2 | 3 | public interface IOrder { 4 | 5 | void pay() throws InterruptedException; 6 | 7 | void show(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/interview/annotation/ObjectFactory.java: -------------------------------------------------------------------------------- 1 | package com.cipher.interview.annotation; 2 | 3 | import org.junit.Test; 4 | 5 | import java.lang.annotation.Annotation; 6 | import java.lang.reflect.InvocationTargetException; 7 | import java.lang.reflect.Proxy; 8 | import java.util.LinkedList; 9 | 10 | /** 11 | * @author cipher 12 | */ 13 | @SuppressWarnings("unchecked") 14 | public class ObjectFactory { 15 | 16 | public static T newInstance(Class clazz) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { 17 | 18 | Annotation[] annotations = clazz.getAnnotations(); 19 | LinkedList aspects = new LinkedList<>(); 20 | 21 | for (Annotation annotation : annotations) { 22 | if (annotation instanceof Aspect) { 23 | Class type = ((Aspect) annotation).type(); 24 | IAspect aspect = (IAspect) (type.getConstructor().newInstance()); 25 | aspects.push(aspect); 26 | } 27 | } 28 | 29 | T inst = clazz.getConstructor().newInstance(); 30 | return (T) Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), (proxy, method, args) -> { 31 | aspects.forEach(IAspect::before); 32 | Object result = method.invoke(inst); 33 | aspects.forEach(IAspect::after); 34 | return result; 35 | }); 36 | } 37 | 38 | @Test 39 | public void test() throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, InterruptedException { 40 | IOrder order = ObjectFactory.newInstance(Order.class); 41 | order.pay(); 42 | order.show(); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/interview/annotation/Order.java: -------------------------------------------------------------------------------- 1 | package com.cipher.interview.annotation; 2 | 3 | import org.junit.Test; 4 | 5 | import java.lang.reflect.Proxy; 6 | 7 | @Aspect(type = TimeUsageAspect.class) 8 | public class Order implements IOrder { 9 | 10 | int state = 0; 11 | 12 | @Override 13 | public void pay() throws InterruptedException { 14 | Thread.sleep(50); 15 | this.state = 1; 16 | } 17 | 18 | @Override 19 | public void show() { 20 | System.out.println("order status:" + this.state); 21 | } 22 | 23 | @Test 24 | public void testProxy() throws InterruptedException { 25 | IOrder order = new Order(); 26 | IOrder proxy = (IOrder) Proxy.newProxyInstance(Order.class.getClassLoader(), new Class[]{IOrder.class}, (proxy1, method, args) -> { 27 | System.out.println("before invoke method:" + method); 28 | return method.invoke(order); 29 | }); 30 | proxy.pay(); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/interview/annotation/TimeUsageAspect.java: -------------------------------------------------------------------------------- 1 | package com.cipher.interview.annotation; 2 | 3 | public class TimeUsageAspect implements IAspect { 4 | 5 | long start; 6 | 7 | @Override 8 | public void before() { 9 | start = System.currentTimeMillis(); 10 | } 11 | 12 | @Override 13 | public void after() { 14 | long usage = System.currentTimeMillis() - start; 15 | System.out.format("time usage : %dms\n", usage); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/interview/collection/RandomStringGenerator.java: -------------------------------------------------------------------------------- 1 | package com.cipher.interview.collection; 2 | 3 | import java.util.Arrays; 4 | import java.util.Iterator; 5 | import java.util.List; 6 | 7 | /** 8 | * @author cipher 9 | */ 10 | public class RandomStringGenerator implements Iterable { 11 | 12 | private final List list; 13 | 14 | public RandomStringGenerator(List list) { 15 | this.list = list; 16 | } 17 | 18 | @Override 19 | public Iterator iterator() { 20 | return new Iterator() { 21 | @Override 22 | public boolean hasNext() { 23 | return true; 24 | } 25 | 26 | @Override 27 | public T next() { 28 | return list.get((int) (list.size() * Math.random())); 29 | } 30 | }; 31 | } 32 | 33 | public static void main(String[] args) { 34 | List list = Arrays.asList("List", "Tree", "Array"); 35 | RandomStringGenerator gen = new RandomStringGenerator<>(list); 36 | for (String s : gen) { 37 | System.out.println(s); 38 | } 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/interview/proxy/IOrder.java: -------------------------------------------------------------------------------- 1 | package com.cipher.interview.proxy; 2 | 3 | public interface IOrder { 4 | 5 | void pay() throws InterruptedException; 6 | 7 | void show(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/interview/proxy/Order.java: -------------------------------------------------------------------------------- 1 | package com.cipher.interview.proxy; 2 | 3 | /** 4 | * @author cipher 5 | */ 6 | public class Order implements IOrder { 7 | 8 | int state = 0; 9 | 10 | @Override 11 | public void pay() throws InterruptedException { 12 | Thread.sleep(50); 13 | this.state = 1; 14 | } 15 | 16 | @Override 17 | public void show() { 18 | System.out.println("order status:" + this.state); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/interview/proxy/ProxyExampleTest.java: -------------------------------------------------------------------------------- 1 | package com.cipher.interview.proxy; 2 | 3 | import org.junit.Test; 4 | 5 | import java.lang.reflect.InvocationTargetException; 6 | 7 | /** 8 | * @author cipher 9 | */ 10 | public class ProxyExampleTest { 11 | 12 | @Test 13 | public void testProxy() throws InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException { 14 | IOrder order = Aspect.getProxy(Order.class, "com.cipher.interview.proxy.TimeUsageAspect"); 15 | order.pay(); 16 | order.show(); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/interview/proxy/TimeUsageAspect.java: -------------------------------------------------------------------------------- 1 | package com.cipher.interview.proxy; 2 | 3 | /** 4 | * @author cipher 5 | */ 6 | public class TimeUsageAspect implements Aspect { 7 | 8 | long start; 9 | 10 | @Override 11 | public void before() { 12 | start = System.currentTimeMillis(); 13 | } 14 | 15 | @Override 16 | public void after() { 17 | long usage = System.currentTimeMillis() - start; 18 | System.out.format("time usage : %dms\n", usage); 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/interview/stream/Event.java: -------------------------------------------------------------------------------- 1 | package com.cipher.interview.stream; 2 | 3 | import java.util.function.Function; 4 | import java.util.stream.Stream; 5 | 6 | /** 7 | * @author cipher 8 | */ 9 | public class Event { 10 | 11 | T data; 12 | 13 | public Event(T data) { 14 | this.data = data; 15 | } 16 | 17 | static class EventData { 18 | Integer id; 19 | String msg; 20 | 21 | public EventData(Integer id, String msg) { 22 | this.id = id; 23 | this.msg = msg; 24 | } 25 | 26 | @Override 27 | public String toString() { 28 | return "EventData{" + "id=" + id + ", msg='" + msg + '\'' + '}'; 29 | } 30 | } 31 | 32 | static class Transforms { 33 | static EventData transform(Integer id) { 34 | switch (id) { 35 | case 0: 36 | return new EventData(id, "Start"); 37 | case 1: 38 | return new EventData(id, "Running"); 39 | case 2: 40 | return new EventData(id, "Done"); 41 | case 3: 42 | return new EventData(id, "Fail"); 43 | default: 44 | return new EventData(id, "Error"); 45 | } 46 | } 47 | } 48 | 49 | Event map(Function f) { 50 | return new Event<>(f.apply(this.data)); 51 | } 52 | 53 | public static void main(String[] args) { 54 | Stream> s = Stream.of(new Event<>(1), new Event<>(2), new Event<>(0), new Event<>(10)); 55 | 56 | s.map(event -> event.map(Transforms::transform)).forEach(e -> { 57 | System.out.println(e.data); 58 | }); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/javassist/Person.java: -------------------------------------------------------------------------------- 1 | package com.cipher.javassist; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: 6 | * @Date: Created in 10:03 2018/9/25 7 | */ 8 | public class Person { 9 | 10 | public String hello(String name) { 11 | System.out.println("test " + name); 12 | return name; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/jmh/Test.java: -------------------------------------------------------------------------------- 1 | package com.cipher.jmh; 2 | 3 | import org.openjdk.jmh.annotations.*; 4 | import org.openjdk.jmh.runner.Runner; 5 | import org.openjdk.jmh.runner.RunnerException; 6 | import org.openjdk.jmh.runner.options.Options; 7 | import org.openjdk.jmh.runner.options.OptionsBuilder; 8 | 9 | import java.util.Collections; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | import java.util.concurrent.TimeUnit; 13 | 14 | @BenchmarkMode(Mode.AverageTime) 15 | @Fork(1) 16 | @Warmup(iterations = 1) 17 | @Measurement(iterations = 5) 18 | @OutputTimeUnit(TimeUnit.MICROSECONDS) 19 | @Threads(1) 20 | @State(Scope.Benchmark) 21 | public class Test { 22 | 23 | private Map hashMap; 24 | private Map synchronizedMap; 25 | 26 | @Setup 27 | public void setUp() { 28 | this.hashMap = new HashMap<>(); 29 | this.synchronizedMap = Collections.synchronizedMap(new HashMap<>()); 30 | } 31 | 32 | @Benchmark 33 | public void testHashMap() { 34 | this.hashMap.put(System.nanoTime(), System.nanoTime()); 35 | } 36 | 37 | @Benchmark 38 | public void testSynchronizedMap() { 39 | this.synchronizedMap.put(System.nanoTime(), System.nanoTime()); 40 | } 41 | 42 | public static void main(String[] args) throws RunnerException { 43 | final Options opts = new OptionsBuilder().include(Test.class.getSimpleName()).build(); 44 | new Runner(opts).run(); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/jvm/FinalizeEscapeGC.java: -------------------------------------------------------------------------------- 1 | package com.cipher.jvm; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: 对象可以在被 GC 时自我拯救; 6 | * 这种机会只有一次,因为一个对象的 finalize() 方法最多只会被系统自动调用一次 7 | * @Date: Created in 16:02 2018/8/16 8 | */ 9 | public class FinalizeEscapeGC { 10 | 11 | public static FinalizeEscapeGC SAVE_HOOK = null; 12 | 13 | public void isAlive() { 14 | System.out.println("yes, I am still alive :)"); 15 | } 16 | 17 | @Override 18 | protected void finalize() throws Throwable { 19 | super.finalize(); 20 | System.out.println("finalize method executed!"); 21 | FinalizeEscapeGC.SAVE_HOOK = this; 22 | } 23 | 24 | public static void main(String[] args) throws Throwable { 25 | SAVE_HOOK = new FinalizeEscapeGC(); 26 | 27 | // 对象第一次成功拯救自己 28 | SAVE_HOOK = null; 29 | System.gc(); 30 | // 因为 finalize 方法优先级很低,所以暂停一段时间等待它 31 | Thread.sleep(500); 32 | if (SAVE_HOOK != null) { 33 | SAVE_HOOK.isAlive(); 34 | } else { 35 | System.out.println("no, I am dead :("); 36 | } 37 | 38 | // 下面这段代码与上面的完全相同,但是这次自我拯救失败了 39 | SAVE_HOOK = null; 40 | System.gc(); 41 | // 因为 finalize 方法优先级很低,所以暂停一段时间等待它 42 | Thread.sleep(500); 43 | if (SAVE_HOOK != null) { 44 | SAVE_HOOK.isAlive(); 45 | } else { 46 | System.out.println("no, I am dead :("); 47 | } 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/jvm/HeapOOM.java: -------------------------------------------------------------------------------- 1 | package com.cipher.jvm; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @Author: CipherCui 8 | * @Description: VM Args: -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError 9 | * 将堆的最小值 -Xms 参数与最大值 -Xmx 参数设置为一样,可以避免堆自动扩展 10 | * -XX:+HeapDumpOnOutOfMemoryError 参数可以让虚拟机出现OOM时 Dump 出当时的内存堆快照 11 | * @Date: Created in 15:19 2018/8/2 12 | */ 13 | public class HeapOOM { 14 | 15 | static class OOMObject { 16 | 17 | } 18 | 19 | public static void main(String[] args) { 20 | List list = new ArrayList<>(); 21 | while (true) { 22 | list.add(new OOMObject()); 23 | } 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/jvm/Hello.java: -------------------------------------------------------------------------------- 1 | package com.cipher.jvm; 2 | 3 | /** 4 | * 对比 class 字节码查看 5 | */ 6 | public class Hello { 7 | 8 | private static String msg = "Goods morning"; 9 | 10 | public static void main(String[] args) { 11 | System.out.println("msg = " + msg); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/jvm/JHSDB_TestCase.java: -------------------------------------------------------------------------------- 1 | package com.cipher.jvm; 2 | 3 | /** 4 | * staticObj, instanceObj, localObj 存放在哪里 5 | * -Xmx10m -XX:+UseSerialGC -XX:-UseCompressedOops 6 | * 7 | * @author: CipherCui 8 | * @since 2020/6/30 9 | */ 10 | public class JHSDB_TestCase { 11 | 12 | static class Test { 13 | static ObjectHolder staticObj = new ObjectHolder(); 14 | ObjectHolder instanceObj = new ObjectHolder(); 15 | 16 | void foo() { 17 | ObjectHolder localObj = new ObjectHolder(); 18 | System.out.println("down"); // 这里设一个断点 19 | } 20 | } 21 | 22 | private static class ObjectHolder { 23 | } 24 | 25 | public static void main(String[] args) { 26 | Test test = new JHSDB_TestCase.Test(); 27 | test.foo(); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/jvm/JavaVMStackOOM.java: -------------------------------------------------------------------------------- 1 | package com.cipher.jvm; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: VM Args: -Xss2M 6 | * @Date: Created in 15:51 2018/8/2 7 | */ 8 | public class JavaVMStackOOM { 9 | 10 | private void dontStop() { 11 | while (true) { 12 | } 13 | } 14 | 15 | public void stackLeakByThread() { 16 | while (true) { 17 | Thread thread = new Thread(() -> { 18 | dontStop(); 19 | }); 20 | thread.start(); 21 | } 22 | } 23 | 24 | public static void main(String[] args) { 25 | JavaVMStackOOM oom = new JavaVMStackOOM(); 26 | oom.stackLeakByThread(); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/jvm/JavaVMStackSOF.java: -------------------------------------------------------------------------------- 1 | package com.cipher.jvm; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: VM Args: -Xss128k 6 | * @Date: Created in 15:40 2018/8/2 7 | */ 8 | public class JavaVMStackSOF { 9 | 10 | private int stackLength = 1; 11 | 12 | public void stackLeak() { 13 | stackLength++; 14 | stackLeak(); 15 | } 16 | 17 | public static void main(String[] args) { 18 | JavaVMStackSOF oom = new JavaVMStackSOF(); 19 | try { 20 | oom.stackLeak(); 21 | } catch (Throwable e) { 22 | System.out.println("stack length: " + oom.stackLength); 23 | throw e; 24 | } 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/jvm/readme.md: -------------------------------------------------------------------------------- 1 | ## Java 虚拟机测试 -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/method_name/FnConverter.java: -------------------------------------------------------------------------------- 1 | package com.cipher.method_name; 2 | 3 | import java.io.Serializable; 4 | import java.lang.invoke.SerializedLambda; 5 | import java.lang.reflect.Method; 6 | 7 | public class FnConverter { 8 | 9 | @FunctionalInterface 10 | public interface Fn extends Serializable { 11 | Object apply(T source); 12 | } 13 | 14 | public static String convertFnToString(Fn fn) { 15 | return fnToFieldName(fn); 16 | } 17 | 18 | public static String fnToFieldName(Fn fn) { 19 | try { 20 | Method method = fn.getClass().getDeclaredMethod("writeReplace"); 21 | method.setAccessible(Boolean.TRUE); 22 | SerializedLambda serializedLambda = (SerializedLambda) method.invoke(fn); 23 | return serializedLambda.getImplMethodName(); 24 | } catch (ReflectiveOperationException e) { 25 | throw new IllegalArgumentException(e); 26 | } 27 | } 28 | 29 | public static void main(String[] args) { 30 | String fieldName = FnConverter.convertFnToString(Foo::getBar); 31 | System.out.println("方法名:" + fieldName); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/method_name/Foo.java: -------------------------------------------------------------------------------- 1 | package com.cipher.method_name; 2 | 3 | public class Foo { 4 | 5 | private Integer bar; 6 | 7 | public Integer getBar() { 8 | return bar; 9 | } 10 | 11 | public void setBar(Integer bar) { 12 | this.bar = bar; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/netty/constant/Command.java: -------------------------------------------------------------------------------- 1 | package com.cipher.netty.constant; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: 6 | * @Date: Created in 14:35 2019/3/19 7 | */ 8 | public class Command { 9 | 10 | public static final Byte LOGIN_REQUEST = 1; 11 | 12 | public static final Byte LOGIN_RESPONSE = 2; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/netty/constant/SerializerAlgorithm.java: -------------------------------------------------------------------------------- 1 | package com.cipher.netty.constant; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: 6 | * @Date: Created in 14:35 2019/3/19 7 | */ 8 | public class SerializerAlgorithm { 9 | 10 | /** 11 | * json 序列化标识 12 | */ 13 | public static final byte JSON = 1; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/netty/protocol/Packet.java: -------------------------------------------------------------------------------- 1 | package com.cipher.netty.protocol; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: 6 | * @Date: Created in 14:26 2019/3/19 7 | */ 8 | public abstract class Packet { 9 | 10 | /** 11 | * 协议版本 12 | */ 13 | private Byte version = 1; 14 | 15 | /** 16 | * 指令 17 | */ 18 | public abstract Byte getCommand(); 19 | 20 | public Byte getVersion() { 21 | return version; 22 | } 23 | 24 | public void setVersion(Byte version) { 25 | this.version = version; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/netty/protocol/request/LoginRequestPacket.java: -------------------------------------------------------------------------------- 1 | package com.cipher.netty.protocol.request; 2 | 3 | import com.cipher.netty.constant.Command; 4 | import com.cipher.netty.protocol.Packet; 5 | 6 | /** 7 | * @Author: CipherCui 8 | * @Description: 9 | * @Date: Created in 14:27 2019/3/19 10 | */ 11 | public class LoginRequestPacket extends Packet { 12 | 13 | private String userId; 14 | 15 | private String username; 16 | 17 | private String password; 18 | 19 | @Override 20 | public Byte getCommand() { 21 | return Command.LOGIN_REQUEST; 22 | } 23 | 24 | public String getUserId() { 25 | return userId; 26 | } 27 | 28 | public void setUserId(String userId) { 29 | this.userId = userId; 30 | } 31 | 32 | public String getUsername() { 33 | return username; 34 | } 35 | 36 | public void setUsername(String username) { 37 | this.username = username; 38 | } 39 | 40 | public String getPassword() { 41 | return password; 42 | } 43 | 44 | public void setPassword(String password) { 45 | this.password = password; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/netty/protocol/response/LoginResponsePacket.java: -------------------------------------------------------------------------------- 1 | package com.cipher.netty.protocol.response; 2 | 3 | import com.cipher.netty.protocol.Packet; 4 | 5 | import static com.cipher.netty.constant.Command.LOGIN_RESPONSE; 6 | 7 | /** 8 | * @Author: CipherCui 9 | * @Description: 10 | * @Date: Created in 16:00 2019/3/19 11 | */ 12 | public class LoginResponsePacket extends Packet { 13 | private boolean success; 14 | 15 | private String reason; 16 | 17 | @Override 18 | public Byte getCommand() { 19 | return LOGIN_RESPONSE; 20 | } 21 | 22 | public boolean isSuccess() { 23 | return success; 24 | } 25 | 26 | public void setSuccess(boolean success) { 27 | this.success = success; 28 | } 29 | 30 | public String getReason() { 31 | return reason; 32 | } 33 | 34 | public void setReason(String reason) { 35 | this.reason = reason; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/netty/serialize/Serializer.java: -------------------------------------------------------------------------------- 1 | package com.cipher.netty.serialize; 2 | 3 | import com.cipher.netty.serialize.impl.JSONSerializer; 4 | 5 | /** 6 | * @Author: CipherCui 7 | * @Description: 8 | * @Date: Created in 14:29 2019/3/19 9 | */ 10 | public interface Serializer { 11 | 12 | Serializer DEFAULT = new JSONSerializer(); 13 | 14 | /** 15 | * 序列化算法 16 | */ 17 | byte getSerializerAlgorithm(); 18 | 19 | /** 20 | * java 对象转换成二进制 21 | */ 22 | byte[] serialize(Object object); 23 | 24 | /** 25 | * 二进制转换成 java 对象 26 | */ 27 | T deserialize(Class clazz, byte[] bytes); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/netty/serialize/impl/JSONSerializer.java: -------------------------------------------------------------------------------- 1 | package com.cipher.netty.serialize.impl; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.cipher.netty.constant.SerializerAlgorithm; 5 | import com.cipher.netty.serialize.Serializer; 6 | 7 | /** 8 | * @Author: CipherCui 9 | * @Description: 10 | * @Date: Created in 14:31 2019/3/19 11 | */ 12 | public class JSONSerializer implements Serializer { 13 | 14 | @Override 15 | public byte getSerializerAlgorithm() { 16 | return SerializerAlgorithm.JSON; 17 | } 18 | 19 | @Override 20 | public byte[] serialize(Object object) { 21 | return JSON.toJSONBytes(object); 22 | } 23 | 24 | @Override 25 | public T deserialize(Class clazz, byte[] bytes) { 26 | return JSON.parseObject(bytes, clazz); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/adapter/GBTwoSocket.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.adapter; 2 | 3 | /** 4 | * 国标二相插座 5 | * Created by cipher on 2017/9/7. 6 | */ 7 | public class GBTwoSocket { 8 | 9 | // 使用二相电流供电 10 | public void powerByTwo() { 11 | System.out.println("使用二相电流供电"); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/adapter/NoteBook.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.adapter; 2 | 3 | /** 4 | * 笔记本类,本身具有三相插头 5 | * Created by cipher on 2017/9/7. 6 | */ 7 | public class NoteBook { 8 | 9 | private ThreePlugIf plug; 10 | 11 | public NoteBook(ThreePlugIf plug) { 12 | this.plug = plug; 13 | } 14 | 15 | // 使用插座充电 16 | public void charge() { 17 | plug.powerFromThree(); 18 | } 19 | 20 | public static void main(String[] args) { 21 | // 插座 22 | GBTwoSocket socket = new GBTwoSocket(); 23 | 24 | // 使用【组合】方式实现适配器模式 25 | ThreePlugIf plug = new TwoToThreeAdapter(socket); 26 | NoteBook nb = new NoteBook(plug); 27 | nb.charge(); 28 | 29 | // 使用【继承】方式实现适配器模式 30 | ThreePlugIf plugByExtend = new TwoToThreeAdapterExtends(); 31 | NoteBook nb2 = new NoteBook(plugByExtend); 32 | nb2.charge(); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/adapter/ThreePlugIf.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.adapter; 2 | 3 | /** 4 | * 三相插头接口 5 | * Created by cipher on 2017/9/7. 6 | */ 7 | public interface ThreePlugIf { 8 | 9 | /** 10 | * 接受三相电流供电 11 | */ 12 | void powerFromThree(); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/adapter/TwoToThreeAdapter.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.adapter; 2 | 3 | /** 4 | * 使用【组合】方式实现适配器模式 5 | * 集成目标接口 ThreePlugIf,组合被适配对象 GBTwoSocket 6 | * 二相转三相适配器 7 | * Created by cipher on 2017/9/7. 8 | */ 9 | public class TwoToThreeAdapter implements ThreePlugIf { 10 | 11 | private GBTwoSocket twoSocket; 12 | 13 | public TwoToThreeAdapter(GBTwoSocket socket) { 14 | this.twoSocket = socket; 15 | } 16 | 17 | public void powerFromThree() { 18 | System.out.println("转换"); 19 | this.twoSocket.powerByTwo(); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/adapter/TwoToThreeAdapterExtends.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.adapter; 2 | 3 | /** 4 | * 使用【继承】方式实现适配器模式 5 | * 二相转三相适配器 6 | * Created by cipher on 2017/9/7. 7 | */ 8 | public class TwoToThreeAdapterExtends extends GBTwoSocket implements ThreePlugIf { 9 | 10 | public void powerFromThree() { 11 | System.out.println("转换"); 12 | this.powerByTwo(); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/adapter/readme.md: -------------------------------------------------------------------------------- 1 | ## 适配器模式 2 | 3 | ### 概念 4 | 适配器模式将一个类的接口,转换为客户期望的另外一个接口。使得原本由于接口不兼容而不能一起工作 5 | 的那些类可以在一起工作。 6 | 7 | ### 组成 8 | - Client(客户端):笔记本 9 | - Target(目标接口):三相插头 10 | - Adapter(适配器):二相转三相适配器 11 | - Adaptee(被适配类):二相插座 12 | 13 | ### 分类 14 | 15 | #### 组合 16 | 采用组合方式的适配器称为【对象】适配器 17 | 18 | 特点:把”被适配者“作为一个对象组合到适配器类中,以修改目标接口包装被适配者。 19 | 20 | #### 继承(单一、重用性低) 21 | 采用继承方式的适配器称为【类】适配器 22 | 23 | 特点:通过继承被适配类和实现目标接口,实现对目标接口的匹配,单一的为某个类而实现适配。 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/chain/CEO.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.chain; 2 | 3 | /** 4 | * CEO 5 | *

6 | * Created by cipher on 2017/9/12. 7 | */ 8 | public class CEO extends PriceHandler { 9 | 10 | public void processDiscount(float discount) { 11 | if (discount <= 0.55f) { 12 | System.out.format("%s批准了折扣:%.2f%n", this.getClass().getName(), discount); 13 | } else { 14 | System.out.format("%s拒绝了折扣:%.2f%n", this.getClass().getName(), discount); 15 | } 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/chain/Client.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.chain; 2 | 3 | /** 4 | * 责任链模式测试类 5 | * Created by cipher on 2017/9/12. 6 | */ 7 | public class Client { 8 | 9 | public static void main(String[] args) { 10 | Custom custom = new Custom(PriceHandlerFactory.createPriceHandler()); 11 | custom.requestDiscount(0.31f); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/chain/Custom.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.chain; 2 | 3 | /** 4 | * 客户,请求折扣 5 | * Created by cipher on 2017/9/12. 6 | */ 7 | public class Custom { 8 | 9 | private PriceHandler priceHandler; 10 | 11 | public Custom(PriceHandler priceHandler) { 12 | this.priceHandler = priceHandler; 13 | } 14 | 15 | public void requestDiscount(float discount) { 16 | this.priceHandler.processDiscount(discount); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/chain/Director.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.chain; 2 | 3 | /** 4 | * 销售总监,可以批准 40% 以内的折扣 5 | *

6 | * Created by cipher on 2017/9/12. 7 | */ 8 | public class Director extends PriceHandler { 9 | 10 | public void processDiscount(float discount) { 11 | if (discount <= 0.4f) { 12 | System.out.format("%s批准了折扣:%.2f%n", this.getClass().getName(), discount); 13 | } else { 14 | this.getSuccessor().processDiscount(discount); 15 | } 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/chain/Lead.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.chain; 2 | 3 | /** 4 | * 销售小组长,可以批准 15% 以内的折扣 5 | *

6 | * Created by cipher on 2017/9/12. 7 | */ 8 | public class Lead extends PriceHandler { 9 | 10 | public void processDiscount(float discount) { 11 | if (discount <= 0.15f) { 12 | System.out.format("%s批准了折扣:%.2f%n", this.getClass().getName(), discount); 13 | } else { 14 | this.getSuccessor().processDiscount(discount); 15 | } 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/chain/Manager.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.chain; 2 | 3 | /** 4 | * 销售经理,可以批准 30% 以内的折扣 5 | *

6 | * Created by cipher on 2017/9/12. 7 | */ 8 | public class Manager extends PriceHandler { 9 | 10 | public void processDiscount(float discount) { 11 | if (discount <= 0.3f) { 12 | System.out.format("%s批准了折扣:%.2f%n", this.getClass().getName(), discount); 13 | } else { 14 | this.getSuccessor().processDiscount(discount); 15 | } 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/chain/PriceHandler.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.chain; 2 | 3 | /** 4 | * 价格处理人抽象类,负责处理客户的折扣申请 5 | * Created by cipher on 2017/9/12. 6 | */ 7 | public abstract class PriceHandler { 8 | 9 | /** 10 | * 直接后继,用于传递请求 11 | */ 12 | private PriceHandler successor; 13 | 14 | public void setSuccessor(PriceHandler successor) { 15 | this.successor = successor; 16 | } 17 | 18 | public PriceHandler getSuccessor() { 19 | return this.successor; 20 | } 21 | 22 | /** 23 | * 处理折扣申请 24 | * 25 | * @param discount 26 | */ 27 | public abstract void processDiscount(float discount); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/chain/PriceHandlerFactory.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.chain; 2 | 3 | /** 4 | * Created by cipher on 2017/9/12. 5 | */ 6 | public class PriceHandlerFactory { 7 | 8 | /** 9 | * 创建 PriceHandlerFactory 的工厂方法 10 | * 11 | * @return 12 | */ 13 | public static PriceHandler createPriceHandler() { 14 | PriceHandler ceo = new CEO(); 15 | PriceHandler vp = new VicePresident(); 16 | PriceHandler director = new Director(); 17 | PriceHandler manager = new Manager(); 18 | PriceHandler lead = new Lead(); 19 | PriceHandler sales = new Sales(); 20 | 21 | sales.setSuccessor(lead); 22 | lead.setSuccessor(manager); 23 | manager.setSuccessor(director); 24 | director.setSuccessor(vp); 25 | vp.setSuccessor(ceo); 26 | 27 | return sales; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/chain/Sales.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.chain; 2 | 3 | /** 4 | * 销售人员,可以批准 5% 以内的折扣 5 | *

6 | * Created by cipher on 2017/9/12. 7 | */ 8 | public class Sales extends PriceHandler { 9 | 10 | public void processDiscount(float discount) { 11 | if (discount <= 0.05f) { 12 | System.out.format("%s批准了折扣:%.2f%n", this.getClass().getName(), discount); 13 | } else { 14 | this.getSuccessor().processDiscount(discount); 15 | } 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/chain/VicePresident.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.chain; 2 | 3 | /** 4 | * 销售副总裁,可以批准 50% 以内的折扣 5 | *

6 | * Created by cipher on 2017/9/12. 7 | */ 8 | public class VicePresident extends PriceHandler { 9 | 10 | public void processDiscount(float discount) { 11 | if (discount <= 0.5f) { 12 | System.out.format("%s批准了折扣:%.2f%n", this.getClass().getName(), discount); 13 | } else { 14 | this.getSuccessor().processDiscount(discount); 15 | } 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/chain/readme.md: -------------------------------------------------------------------------------- 1 | ## 责任链模式 2 | 3 | ### 概念 4 | 将接收者对象(Handler,持有一个自身类型的引用)连成一条链,并在该链上传递请求,直到有一个接收者对象处理它。 5 | 通过让更多对象有机会处理请求,避免了请求发送者(Client)和接收者之间的耦合。 6 | 7 | 发出请求的客户端并不知道链上的哪一个接收者会处理这个请求,从而实现了客户端和接收者之间的解耦。 8 | 9 | 开闭原则:对扩展开放,对变更关闭。 10 | 11 | 缺点:时间、内存 12 | 13 | 应用:Java异常机制、JS事件机制、Java Web过滤器Filter(Spring Security) -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/factory/abs/Customer.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.factory.abs; 2 | 3 | import com.cipher.pattern.factory.abs.factory.FactoryBMW; 4 | import com.cipher.pattern.factory.abs.factory.FactoryBMW320; 5 | import com.cipher.pattern.factory.abs.factory.FactoryBMW523; 6 | 7 | /** 8 | * 抽象工厂模式客户端 9 | * Created by cipher on 2017/9/6. 10 | */ 11 | public class Customer { 12 | 13 | public static void main(String[] args) { 14 | FactoryBMW factoryBMW320 = new FactoryBMW320(); 15 | factoryBMW320.createEngie(); 16 | factoryBMW320.createAircondition(); 17 | 18 | FactoryBMW factoryBMW523 = new FactoryBMW523(); 19 | factoryBMW523.createEngie(); 20 | factoryBMW523.createAircondition(); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/factory/abs/factory/FactoryBMW.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.factory.abs.factory; 2 | 3 | import com.cipher.pattern.factory.abs.product.Aircondition; 4 | import com.cipher.pattern.factory.abs.product.Engine; 5 | 6 | /** 7 | * 抽象工厂类,制造多个产品 8 | * Created by cipher on 2017/9/6. 9 | */ 10 | public interface FactoryBMW { 11 | 12 | // 制造发动机 13 | Engine createEngie(); 14 | 15 | // 制造空调 16 | Aircondition createAircondition(); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/factory/abs/factory/FactoryBMW320.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.factory.abs.factory; 2 | 3 | import com.cipher.pattern.factory.abs.product.Aircondition; 4 | import com.cipher.pattern.factory.abs.product.AirconditionA; 5 | import com.cipher.pattern.factory.abs.product.Engine; 6 | import com.cipher.pattern.factory.abs.product.EngineA; 7 | 8 | /** 9 | * 为宝马320系列生产配件 10 | * Created by cipher on 2017/9/6. 11 | */ 12 | public class FactoryBMW320 implements FactoryBMW { 13 | 14 | public Engine createEngie() { 15 | return new EngineA(); 16 | } 17 | 18 | public Aircondition createAircondition() { 19 | return new AirconditionA(); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/factory/abs/factory/FactoryBMW523.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.factory.abs.factory; 2 | 3 | import com.cipher.pattern.factory.abs.product.*; 4 | 5 | /** 6 | * 为宝马523系列生产配件 7 | * Created by cipher on 2017/9/6. 8 | */ 9 | public class FactoryBMW523 implements FactoryBMW { 10 | 11 | public Engine createEngie() { 12 | return new EngineB(); 13 | } 14 | 15 | public Aircondition createAircondition() { 16 | return new AirconditionB(); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/factory/abs/product/Aircondition.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.factory.abs.product; 2 | 3 | /** 4 | * 空调抽象产品类 5 | * Created by cipher on 2017/9/6. 6 | */ 7 | abstract public class Aircondition { 8 | } 9 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/factory/abs/product/AirconditionA.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.factory.abs.product; 2 | 3 | /** 4 | * 空调A 5 | * Created by cipher on 2017/9/6. 6 | */ 7 | public class AirconditionA extends Aircondition { 8 | 9 | public AirconditionA() { 10 | System.out.println("制造 --> AirconditionA"); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/factory/abs/product/AirconditionB.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.factory.abs.product; 2 | 3 | /** 4 | * 空调B 5 | * Created by cipher on 2017/9/6. 6 | */ 7 | public class AirconditionB extends Aircondition { 8 | 9 | public AirconditionB() { 10 | System.out.println("制造 --> AirconditionB"); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/factory/abs/product/Engine.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.factory.abs.product; 2 | 3 | /** 4 | * 发动机抽象产品类 5 | * Created by cipher on 2017/9/6. 6 | */ 7 | abstract public class Engine { 8 | } 9 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/factory/abs/product/EngineA.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.factory.abs.product; 2 | 3 | /** 4 | * 发动机A 5 | * Created by cipher on 2017/9/6. 6 | */ 7 | public class EngineA extends Engine { 8 | 9 | public EngineA() { 10 | System.out.println("制造 --> EngineA"); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/factory/abs/product/EngineB.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.factory.abs.product; 2 | 3 | /** 4 | * 发动机B 5 | * Created by cipher on 2017/9/6. 6 | */ 7 | public class EngineB extends Engine { 8 | 9 | public EngineB() { 10 | System.out.println("制造 --> EngineB"); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/factory/abs/readme.md: -------------------------------------------------------------------------------- 1 | ## 抽象工厂模式 2 | 3 | ### 例子背景 4 | 随着客户的要求越来越高,宝马车需要不同配置的空调和发动机等配件。 5 | 于是这个工厂开始生产空调和发动机,用来组装汽车。 6 | 这时候工厂有两个系列的产品:空调和发动机。 7 | - 宝马320系列配置A型号空调和A型号发动机, 8 | - 宝马230系列配置B型号空调和B型号发动机。 9 | 10 | ### 说明 11 | 抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象。 12 | 比如宝马320系列使用空调型号A和发动机型号A,而宝马230系列使用空调型号B和发动机型号B, 13 | 那么使用抽象工厂模式,在为320系列生产相关配件时,就无需制定配件的型号, 14 | 它会自动根据车型生产对应的配件型号A。 15 | 16 | 工厂方法模式中一个工厂只能生产一个产品,所以当产品一多的时候,就会产生很多相应的工厂。 17 | 而抽象工厂模式与工厂方法模式的区别就在于,一个工厂可以生产多个产品,在业务中往往是生产 18 | 多个同系列的产品,例如本例的空调和发动机。 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/factory/method/Customer.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.factory.method; 2 | 3 | import com.cipher.pattern.factory.method.factory.FactoryBMW; 4 | import com.cipher.pattern.factory.method.factory.FactoryBMW320; 5 | import com.cipher.pattern.factory.method.factory.FactoryBMW523; 6 | 7 | /** 8 | * 工厂方法模式客户端 9 | * Created by cipher on 2017/9/6. 10 | */ 11 | public class Customer { 12 | 13 | public static void main(String[] args) { 14 | FactoryBMW factoryBMW320 = new FactoryBMW320(); 15 | factoryBMW320.createBMW(); 16 | 17 | FactoryBMW factoryBMW523 = new FactoryBMW523(); 18 | factoryBMW523.createBMW(); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/factory/method/factory/FactoryBMW.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.factory.method.factory; 2 | 3 | import com.cipher.pattern.factory.method.product.BMW; 4 | 5 | /** 6 | * 抽象工厂类 7 | * Created by cipher on 2017/9/6. 8 | */ 9 | public interface FactoryBMW { 10 | 11 | BMW createBMW(); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/factory/method/factory/FactoryBMW320.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.factory.method.factory; 2 | 3 | import com.cipher.pattern.factory.method.product.BMW; 4 | import com.cipher.pattern.factory.method.product.BMW320; 5 | 6 | /** 7 | * 具体工厂类 8 | * Created by cipher on 2017/9/6. 9 | */ 10 | public class FactoryBMW320 implements FactoryBMW { 11 | 12 | public BMW createBMW() { 13 | return new BMW320(); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/factory/method/factory/FactoryBMW523.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.factory.method.factory; 2 | 3 | import com.cipher.pattern.factory.method.product.BMW; 4 | import com.cipher.pattern.factory.method.product.BMW523; 5 | 6 | /** 7 | * 具体工厂类 8 | * Created by cipher on 2017/9/6. 9 | */ 10 | public class FactoryBMW523 implements FactoryBMW { 11 | 12 | public BMW createBMW() { 13 | return new BMW523(); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/factory/method/product/BMW.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.factory.method.product; 2 | 3 | /** 4 | * 抽象产品类 5 | * Created by cipher on 2017/9/6. 6 | */ 7 | abstract public class BMW { 8 | 9 | public BMW() { 10 | 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/factory/method/product/BMW320.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.factory.method.product; 2 | 3 | /** 4 | * Created by cipher on 2017/9/6. 5 | */ 6 | public class BMW320 extends BMW { 7 | 8 | public BMW320() { 9 | System.out.println("制造 --> BMW320"); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/factory/method/product/BMW523.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.factory.method.product; 2 | 3 | /** 4 | * Created by cipher on 2017/9/6. 5 | */ 6 | public class BMW523 extends BMW { 7 | 8 | public BMW523() { 9 | System.out.println("制造 --> BMW523"); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/factory/method/readme.md: -------------------------------------------------------------------------------- 1 | ## 工厂方法模式 2 | 3 | 工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使得它可以被子类继承。 4 | 这样在简单工厂模式里集中在工厂方法上的压力可以由工厂方法模式里不同的工厂子类来分担。 5 | 6 | 产品类与简单工厂模式相同,只是工厂类再抽象多一层。 7 | 8 | ### 组成 9 | - 抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。 10 | 是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。 11 | - 具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。 12 | - 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。 13 | - 具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。 14 | 15 | ### 说明 16 | 工厂方法模式使用继承自抽象工厂角色的多个子类来代替简单工厂模式中的“上帝类”。 17 | 正如上面所说,这样便分担了对象承受的压力;而且这样使得结构变得灵活起来, 18 | 当有新的产品产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成, 19 | 那么就可以被客户使用,而不必去修改任何已有的代码。 20 | 21 | 22 | ### 问题 23 | 工厂方法模式仿佛已经很完美的对对象的创建进行了包装, 24 | 使得客户程序中仅仅处理抽象产品角色提供的接口,但使得对象的数量成倍增长。 25 | 当产品种类非常多时,会出现大量的与之对应的工厂对象,这不是我们所希望的。 26 | 27 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/factory/readme.md: -------------------------------------------------------------------------------- 1 | ## 工厂模式 2 | 3 | ### 问题 4 | 在面向对象编程中, 最通常的方法是一个 new 操作符产生一个对象实例,new 操作符就是用来构造对象实例的。 5 | 但是在一些情况下, new 操作符直接生成对象会带来一些问题。举例来说, 许多类型对象的创造需要一系列的步骤: 6 | 7 | - 你可能需要计算或取得对象的初始设置; 8 | - 选择生成哪个子对象实例; 9 | - 生成你需要的对象之前必须先生成一些辅助功能的对象。 10 | 11 | 在这些情况,新对象的建立就是一个 “过程”,不仅是一个操作,像一部大机器中的一个齿轮传动。 12 | 13 | ### 解决 14 | 建立一个工厂来创建对象,不必关心构造对象实例的细节和复杂过程。 15 | 16 | ### 适用场景 17 | - 有一组类似的对象需要创建 18 | - 在编码时不能预见需要创建哪种类的实例 19 | - 系统需要考虑扩展性,降低耦合度 20 | 21 | ### 分类 22 | - 简单工厂模式 23 | - 工厂方法模式 24 | - 抽象工厂模式 25 | 26 | ### 区别 27 | 简单工厂模式是工厂方法模式的一种特例。 28 | 29 | 工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。 30 | 工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。 31 | 32 | #### 工厂方法模式 33 | 一个抽象产品类,可以派生出多个具体产品类。 34 | 一个抽象工厂类,可以派生出多个具体工厂类。 35 | 每个具体工厂类只能创建一个具体产品类的实例。 36 | 37 | #### 抽象工厂模式 38 | 多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。 39 | 一个抽象工厂类,可以派生出多个具体工厂类。 40 | 每个具体工厂类可以创建多个具体产品类的实例。 41 | 42 | ### 总结 43 | 无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们都属于工厂模式, 44 | 在形式和特点上也是极为相似的,他们的最终目的都是为了解耦。 45 | 在使用时,我们不必去在意这个模式到底工厂方法模式还是抽象工厂模式, 46 | 因为他们之间的演变常常是令人琢磨不透的。经常你会发现,明明使用的工厂方法模式, 47 | 当新需求来临,稍加修改,加入了一个新方法后,由于类中的产品构成了不同等级结构中的产品族, 48 | 它就变成抽象工厂模式了;而对于抽象工厂模式,当减少一个方法使的提供的产品不再构成产品族 49 | 之后,它就演变成了工厂方法模式。所以,在使用工厂模式时, 50 | 只需要关心降低耦合度的目的是否达到了。 51 | 52 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/factory/simple/Customer.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.factory.simple; 2 | 3 | import com.cipher.pattern.factory.simple.factory.Factory; 4 | import com.cipher.pattern.factory.simple.product.BMW; 5 | 6 | /** 7 | * 简单工厂方法模式客户端 8 | * Created by cipher on 2017/9/6. 9 | */ 10 | public class Customer { 11 | 12 | public static void main(String[] args) { 13 | Factory factory = new Factory(); 14 | BMW bmw320 = factory.createBMW(320); 15 | BMW bmw523 = factory.createBMW(523); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/factory/simple/factory/Factory.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.factory.simple.factory; 2 | 3 | import com.cipher.pattern.factory.simple.product.BMW; 4 | import com.cipher.pattern.factory.simple.product.BMW320; 5 | import com.cipher.pattern.factory.simple.product.BMW523; 6 | 7 | /** 8 | * 简单工厂类 9 | * Created by cipher on 2017/9/6. 10 | */ 11 | public class Factory { 12 | 13 | public BMW createBMW(int type) { 14 | switch (type) { 15 | case 320: 16 | return new BMW320(); 17 | case 523: 18 | return new BMW523(); 19 | default: 20 | return null; 21 | } 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/factory/simple/product/BMW.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.factory.simple.product; 2 | 3 | /** 4 | * 抽象产品类 5 | * Created by cipher on 2017/9/6. 6 | */ 7 | abstract public class BMW { 8 | public BMW() { 9 | 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/factory/simple/product/BMW320.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.factory.simple.product; 2 | 3 | /** 4 | * Created by cipher on 2017/9/6. 5 | */ 6 | public class BMW320 extends BMW { 7 | 8 | public BMW320() { 9 | System.out.println("制造 --> BMW320"); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/factory/simple/product/BMW523.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.factory.simple.product; 2 | 3 | /** 4 | * Created by cipher on 2017/9/6. 5 | */ 6 | public class BMW523 extends BMW { 7 | 8 | public BMW523() { 9 | System.out.println("制造 --> BMW523"); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/factory/simple/readme.md: -------------------------------------------------------------------------------- 1 | ## 简单工厂模式 2 | 3 | 定义一个用于创建对象的接口。 4 | 5 | ### 组成 6 | - 工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑,用来创建产品 7 | - 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。 8 | - 具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。 9 | 10 | ### 问题 11 | 每增加一种新型车,都要在工厂类中增加相应的创建业务逻辑( 12 | createBMW(int type)方法需要新增case),这显然是违背开闭原则的。 13 | 可想而知对于新产品的加入,工厂类是很被动的。对于这样的工厂类, 14 | 我们称它为全能类或者上帝类。 15 | 16 | 我们举的例子是最简单的情况,而在实际应用中,很可能产品是一个多层次的树状结构。 17 | 由于简单工厂模式中只有一个工厂类来对应这些产品,所以这可能会把我们的上帝累坏了, 18 | 也累坏了我们这些程序员 19 | 20 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/observer/custom/Client.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.observer.custom; 2 | 3 | /** 4 | * 观察者模式测试类 5 | * Created by cipher on 2017/9/8. 6 | */ 7 | public class Client { 8 | 9 | public static void main(String[] args) { 10 | // 创建目标 11 | WeatherStationSubject ws = new WeatherStationSubject(); 12 | // 创建观察者 13 | ConcreteObserver girlfriend = new ConcreteObserver("女朋友"); 14 | ConcreteObserver mom = new ConcreteObserver("老妈"); 15 | // 注册观察者 16 | ws.attach(girlfriend, mom); 17 | // 目标发布天气 18 | ws.setWeather("天气晴朗"); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/observer/custom/ConcreteObserver.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.observer.custom; 2 | 3 | /** 4 | * 具体的观察者对象,实现更新的方法,使自己的状态和目标的状态保持一致 5 | * Created by cipher on 2017/9/8. 6 | */ 7 | public class ConcreteObserver implements Observer { 8 | 9 | private String name; 10 | 11 | private String weacher; 12 | 13 | public ConcreteObserver(String name) { 14 | this.name = name; 15 | } 16 | 17 | public void update(Subject subject) { 18 | this.weacher = ((WeatherStationSubject) subject).getWeather(); 19 | System.out.println(String.format("【拉模型】%s收到通知:%s", this.name, this.weacher)); 20 | } 21 | 22 | public void updateByPush(String content) { 23 | this.weacher = content; 24 | System.out.println(String.format("【推模型】%s收到通知:%s", this.name, this.weacher)); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/observer/custom/Observer.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.observer.custom; 2 | 3 | /** 4 | * 观察者接口,定义一个更新的方法 5 | * Created by cipher on 2017/9/8. 6 | */ 7 | public interface Observer { 8 | 9 | /** 10 | * 【拉模型】 11 | * 更新的方法 12 | * 13 | * @param subject 传入目标对象,方便获取目标对象的数据 14 | */ 15 | void update(Subject subject); 16 | 17 | /** 18 | * 【推模型】 19 | * 更新的方法 20 | * 21 | * @param content 只传入目标对象的某些信息 22 | */ 23 | void updateByPush(String content); 24 | 25 | } 26 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/observer/custom/Subject.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.observer.custom; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * 目标对象,它知道它的观察者,并提供添加和删除观察者的接口 8 | * Created by cipher on 2017/9/8. 9 | */ 10 | public class Subject { 11 | 12 | // 用于保存注册的观察者对象 13 | private List observers = new ArrayList(); 14 | 15 | // 添加观察者 16 | public void attach(Observer... os) { 17 | if (os == null || os.length == 0) return; 18 | for (Observer o : os) { 19 | this.observers.add(o); 20 | } 21 | } 22 | 23 | // 删除观察者 24 | public void detach(Observer o) { 25 | observers.remove(o); 26 | } 27 | 28 | // 通知所有注册的观察者对象 29 | protected void notifyObservers() { 30 | for (Observer o : observers) { 31 | o.update(this); 32 | } 33 | } 34 | 35 | // 【推模型】通知所有注册的观察者对象 36 | protected void notifyObservers(String content) { 37 | for (Observer o : observers) { 38 | o.updateByPush(content); 39 | } 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/observer/custom/WeatherStationSubject.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.observer.custom; 2 | 3 | /** 4 | * 气象站类 5 | * 具体的目标对象,负责把有关状态存入到相应的观察者对象中 6 | * Created by cipher on 2017/9/8. 7 | */ 8 | public class WeatherStationSubject extends Subject { 9 | 10 | private String weather; 11 | 12 | public String getWeather() { 13 | return weather; 14 | } 15 | 16 | public void setWeather(String weather) { 17 | this.weather = weather; 18 | // 状态改变时,通知观察者 19 | this.notifyObservers(); 20 | this.notifyObservers(weather); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/observer/custom/readme.md: -------------------------------------------------------------------------------- 1 | ## 自定义实现观察者模式 2 | 3 | - 推模型 4 | - 拉模型 -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/observer/jdk/Client.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.observer.jdk; 2 | 3 | 4 | /** 5 | * 观察者模式测试类 6 | * Created by cipher on 2017/9/8. 7 | */ 8 | public class Client { 9 | 10 | public static void main(String[] args) { 11 | // 创建目标 12 | WeatherStationSubject ws = new WeatherStationSubject(); 13 | // 创建观察者 14 | ConcreteObserver girlfriend = new ConcreteObserver("女朋友"); 15 | ConcreteObserver mom = new ConcreteObserver("老妈"); 16 | // 注册观察者 17 | ws.addObserver(girlfriend); 18 | ws.addObserver(mom); 19 | // 目标发布天气 20 | ws.setWeather("天气晴朗"); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/observer/jdk/ConcreteObserver.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.observer.jdk; 2 | 3 | import java.util.Observable; 4 | import java.util.Observer; 5 | 6 | /** 7 | * 具体的观察者对象,实现更新的方法,使自己的状态和目标的状态保持一致 8 | * Created by cipher on 2017/9/8. 9 | */ 10 | public class ConcreteObserver implements Observer { 11 | 12 | private String name; 13 | 14 | private String weacher; 15 | 16 | public ConcreteObserver(String name) { 17 | this.name = name; 18 | } 19 | 20 | public void update(Observable o, Object arg) { 21 | this.weacher = ((WeatherStationSubject) o).getWeather(); 22 | System.out.println(String.format("【JDK】%s收到通知:%s", this.name, this.weacher)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/observer/jdk/WeatherStationSubject.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.observer.jdk; 2 | 3 | 4 | import java.util.Observable; 5 | 6 | /** 7 | * 气象站类 8 | * 具体的目标对象,负责把有关状态存入到相应的观察者对象中 9 | * Created by cipher on 2017/9/8. 10 | */ 11 | public class WeatherStationSubject extends Observable { 12 | 13 | private String weather; 14 | 15 | public String getWeather() { 16 | return weather; 17 | } 18 | 19 | public void setWeather(String weather) { 20 | this.weather = weather; 21 | // 状态改变时,通知观察者 22 | // 需要先调用 setChanged 23 | this.setChanged(); 24 | // 无参是拉模型(会把 this 传给 update 方法),有参是推模型 25 | this.notifyObservers(); 26 | } 27 | 28 | 29 | 30 | } 31 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/observer/jdk/readme.md: -------------------------------------------------------------------------------- 1 | ## 使用 JDK 提供的类实现观察者模式 2 | 3 | ### 与自定义实现的区别 4 | 5 | - 不需要再定义观察则和目标的接口了; 6 | - 具体的目标实现里不需要再维护观察者的注册信息; 7 | - 触发通知的方式有改变,要先调用`setChanged`方法,这是为了帮助实现更精确的触发控制而提供的功能; 8 | - 具体的观察者实现里面,`update`方法同时支持推模型和拉模型; -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/observer/readme.md: -------------------------------------------------------------------------------- 1 | ## 观察者模式 2 | 3 | ### 定义 4 | 定义对象间的一种一对多的依赖关系。当一个对象的状态发生改变时,所有依赖于它的对象 5 | 都得到通知并自动更新。 6 | 7 | ### 场景 8 | 观察者 Observer(小明的女朋友、老妈)——【订阅】——>> 气象站 Subject(小明) 9 | 10 | ### 分类 11 | 12 | #### 推模型 13 | - 假定目标对象知道观察者需要的数据。 14 | 15 | - 目标对象主动向观察者推送目标的详细信息,推送的信息通常是目标对象的全部或部分数据。 16 | 17 | - 会使观察者难以复用。 18 | 19 | #### 拉模型 20 | - 假定目标对象不知道观察则具体需要什么数据。 21 | 22 | - 目标对象在通知观察者的时候,只传递少量信息。 23 | 24 | - 如果观察者需要更具体的信息,由观察者主动到目标对象中获取,相当于观察者从目标对象中拉数据。 25 | 26 | - 一般这种模型的实现中,会把目标对象自身通过 update 方法传递给观察者。 27 | 28 | ### 优点 29 | - 实现了观察者和目标之间的抽象耦合 30 | - 实现了动态联动 31 | - 支持广播通信 32 | 33 | ### 缺点 34 | 可能会引起无谓的操作,所有观察者都会进行 update 操作 35 | 36 | ### 使用场景 37 | - 一个对象(观察者)的操作依赖于另一个对象(目标)的状态变化 38 | - 更改一个对象(目标)时,同时需要连带改变其他对象(观察者),而且不知道究竟有多少个对象需要被连带改变 39 | - 一个对象(目标)必须通知其他对象(观察者) -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/observer/special/Client.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.observer.special; 2 | 3 | 4 | /** 5 | * 观察者模式测试类 6 | * Created by cipher on 2017/9/8. 7 | */ 8 | public class Client { 9 | 10 | public static void main(String[] args) { 11 | // 创建目标 12 | WeatherStationSubject ws = new WeatherStationSubject(); 13 | // 创建观察者 14 | ConcreteObserver girlfriend = new ConcreteObserver("女朋友"); 15 | girlfriend.setInterestWeacher(new String[]{"晴朗", "下雨"}); 16 | ConcreteObserver mom = new ConcreteObserver("老妈"); 17 | mom.setInterestWeacher(new String[]{"晴朗"}); 18 | // 注册观察者 19 | ws.attach(girlfriend, mom); 20 | // 目标发布天气 21 | ws.setWeather("下雨"); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/observer/special/ConcreteObserver.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.observer.special; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * 具体的观察者对象,实现更新的方法,使自己的状态和目标的状态保持一致 7 | * Created by cipher on 2017/9/8. 8 | */ 9 | public class ConcreteObserver implements Observer { 10 | 11 | private String name; 12 | 13 | private String weather; 14 | 15 | private String[] interestWeacher; 16 | 17 | public ConcreteObserver(String name) { 18 | this.name = name; 19 | } 20 | 21 | public void update(Subject subject) { 22 | System.out.println(String.format("%s收到通知:%s", this.name, this.weather)); 23 | } 24 | 25 | public boolean isInterest(Subject subject) { 26 | this.weather = ((WeatherStationSubject) subject).getWeather(); 27 | if (Arrays.asList(interestWeacher).contains(this.weather)) { 28 | return true; 29 | } 30 | return false; 31 | } 32 | 33 | public void setInterestWeacher(String[] interestWeacher) { 34 | this.interestWeacher = interestWeacher; 35 | } 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/observer/special/Observer.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.observer.special; 2 | 3 | /** 4 | * 观察者接口,定义一个更新的方法 5 | * Created by cipher on 2017/9/8. 6 | */ 7 | public interface Observer { 8 | 9 | /** 10 | * 更新的方法 11 | * 12 | * @param subject 传入目标对象,方便获取目标对象的数据 13 | */ 14 | void update(Subject subject); 15 | 16 | /** 17 | * 根据目标对象判断是否感兴趣 18 | * 19 | * @param subject 20 | * @return 21 | */ 22 | boolean isInterest(Subject subject); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/observer/special/Subject.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.observer.special; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * 目标对象,它知道它的观察者,并提供添加和删除观察者的接口 8 | * Created by cipher on 2017/9/8. 9 | */ 10 | public abstract class Subject { 11 | 12 | // 用于保存注册的观察者对象 13 | private List observers = new ArrayList(); 14 | 15 | // 添加观察者 16 | public void attach(Observer... os) { 17 | if (os == null || os.length == 0) return; 18 | for (Observer o : os) { 19 | this.observers.add(o); 20 | } 21 | } 22 | 23 | // 删除观察者 24 | public void detach(Observer o) { 25 | observers.remove(o); 26 | } 27 | 28 | // 通知所有注册的观察者对象 29 | protected void notifyObservers() { 30 | for (Observer o : observers) { 31 | // 感兴趣才调用更新方法 32 | if (o.isInterest(this)) { 33 | o.update(this); 34 | } 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/observer/special/WeatherStationSubject.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.observer.special; 2 | 3 | /** 4 | * 气象站类 5 | * 具体的目标对象,负责把有关状态存入到相应的观察者对象中 6 | * Created by cipher on 2017/9/8. 7 | */ 8 | public class WeatherStationSubject extends Subject { 9 | 10 | private String weather; 11 | 12 | public String getWeather() { 13 | return weather; 14 | } 15 | 16 | public void setWeather(String weather) { 17 | this.weather = weather; 18 | // 状态改变时,通知观察者 19 | this.notifyObservers(); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/observer/special/readme.md: -------------------------------------------------------------------------------- 1 | ## 观察者模式的衍生 2 | 3 | ### 区别对待观察者 4 | 观察者不是对目标对象所有的状态改变都作出操作,只对自己关心的状态作出操作。 5 | 6 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/proxy/Car.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.proxy; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * 汽车类,实现行驶接口 7 | * Created by cipher on 2017/9/6. 8 | */ 9 | public class Car implements Moveable { 10 | 11 | public void move() { 12 | // 实现行驶 13 | try { 14 | System.out.println("汽车行驶中......"); 15 | Thread.sleep(new Random().nextInt(1000)); 16 | } catch (InterruptedException e) { 17 | e.printStackTrace(); 18 | } 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/proxy/Moveable.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.proxy; 2 | 3 | /** 4 | * 行驶接口类 5 | * Created by cipher on 2017/9/6. 6 | */ 7 | public interface Moveable { 8 | 9 | void move(); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/proxy/dynamic/cglib/CarLogProxy.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.proxy.dynamic.cglib; 2 | 3 | import net.sf.cglib.proxy.Enhancer; 4 | import net.sf.cglib.proxy.MethodInterceptor; 5 | import net.sf.cglib.proxy.MethodProxy; 6 | 7 | import java.lang.reflect.Method; 8 | 9 | /** 10 | * CGLIB 实现动态代理 11 | * Created by cipher on 2017/9/6. 12 | */ 13 | public class CarLogProxy implements MethodInterceptor { 14 | 15 | private Enhancer enhancer = new Enhancer(); 16 | 17 | public Object getProxy(Class clazz) { 18 | // 设置父类 19 | enhancer.setSuperclass(clazz); 20 | enhancer.setCallback(this); 21 | return enhancer.create(); 22 | } 23 | 24 | /** 25 | * 拦截所有目标的方法调用 26 | * 27 | * @param o 目标类的实例 28 | * @param method 目标方法的反射对象 29 | * @param objects 方法的参数 30 | * @param methodProxy 代理类的对象 31 | * @return 32 | * @throws Throwable 33 | */ 34 | @Override 35 | public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { 36 | System.out.println("日志开始......"); 37 | // 代理类调用父类的方法 38 | methodProxy.invokeSuper(o, objects); 39 | System.out.println("日志结束......"); 40 | return null; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/proxy/dynamic/cglib/CarTimeProxy.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.proxy.dynamic.cglib; 2 | 3 | import net.sf.cglib.proxy.Enhancer; 4 | import net.sf.cglib.proxy.MethodInterceptor; 5 | import net.sf.cglib.proxy.MethodProxy; 6 | 7 | import java.lang.reflect.Method; 8 | 9 | /** 10 | * CGLIB 实现动态代理 11 | * Created by cipher on 2017/9/6. 12 | */ 13 | public class CarTimeProxy implements MethodInterceptor { 14 | 15 | private Enhancer enhancer = new Enhancer(); 16 | 17 | public Object getProxy(Class clazz) { 18 | // 设置父类 19 | enhancer.setSuperclass(clazz); 20 | enhancer.setCallback(this); 21 | return enhancer.create(); 22 | } 23 | 24 | /** 25 | * 拦截所有目标的方法调用 26 | * 27 | * @param o 目标类的实例 28 | * @param method 目标方法的反射对象 29 | * @param objects 方法的参数 30 | * @param methodProxy 代理类的对象 31 | * @return 32 | * @throws Throwable 33 | */ 34 | public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { 35 | long start = System.currentTimeMillis(); 36 | System.out.println("开始行驶......"); 37 | // 代理类调用父类的方法 38 | methodProxy.invokeSuper(o, objects); 39 | long end = System.currentTimeMillis(); 40 | System.out.println("结束行驶......行驶时间:" + (end - start) + "毫秒"); 41 | return null; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/proxy/dynamic/cglib/Client.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.proxy.dynamic.cglib; 2 | 3 | import com.cipher.pattern.proxy.Car; 4 | 5 | /** 6 | * CGLIB 动态代理测试类 7 | * Created by cipher on 2017/9/6. 8 | */ 9 | public class Client { 10 | 11 | public static void main(String[] args) { 12 | // 记录时间 13 | CarTimeProxy carTimeProxy = new CarTimeProxy(); 14 | Car carByTime = (Car) carTimeProxy.getProxy(Car.class); 15 | carByTime.move(); 16 | System.out.println("-----------"); 17 | // 记录日志 18 | CarLogProxy carLogProxy = new CarLogProxy(); 19 | Car carByLogTime = (Car) carLogProxy.getProxy(Car.class); 20 | carByLogTime.move(); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/proxy/dynamic/cglib/Train.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.proxy.dynamic.cglib; 2 | 3 | /** 4 | * 火车类 5 | * Created by cipher on 2017/9/6. 6 | */ 7 | public class Train { 8 | 9 | public void move() { 10 | System.out.println("火车行驶中......"); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/proxy/dynamic/cglib/readme.md: -------------------------------------------------------------------------------- 1 | ## CGLIB 动态代理 2 | 3 | 针对类来实现动态代理,对指定的目标类产生一个子类, 4 | 通过方法拦截技术拦截所有父类方法的调用。 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/proxy/dynamic/custom/Client.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.proxy.dynamic.custom; 2 | 3 | import com.cipher.pattern.proxy.Car; 4 | import com.cipher.pattern.proxy.Moveable; 5 | 6 | /** 7 | * 自定义模拟 JDK 动态代理测试类 8 | * Created by cipher on 2017/9/6. 9 | */ 10 | public class Client { 11 | 12 | public static void main(String[] args) throws Exception { 13 | InvocationHandler handler = new TimeHandler(new Car()); 14 | Moveable moveable = (Moveable) Proxy.newProxyInstance(Moveable.class, handler); 15 | moveable.move(); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/proxy/dynamic/custom/InvocationHandler.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.proxy.dynamic.custom; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | /** 6 | * 自定义处理器 7 | * Created by cipher on 2017/9/6. 8 | */ 9 | public interface InvocationHandler { 10 | 11 | void invoke(Object o, Method m) throws Throwable; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/proxy/dynamic/custom/TimeHandler.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.proxy.dynamic.custom; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | /** 6 | * 时间记录处理器 7 | * Created by cipher on 2017/9/6. 8 | */ 9 | public class TimeHandler implements InvocationHandler { 10 | 11 | private Object target; 12 | 13 | public TimeHandler(Object target) { 14 | this.target = target; 15 | } 16 | 17 | public void invoke(Object o, Method m) throws Throwable { 18 | long start = System.currentTimeMillis(); 19 | System.out.println("汽车开始行驶......"); 20 | m.invoke(target); 21 | long end = System.currentTimeMillis(); 22 | System.out.println("汽车结束行驶......行驶时间:" + (end - start) + "毫秒"); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/proxy/dynamic/custom/readme.md: -------------------------------------------------------------------------------- 1 | ## 自定义类模拟 JDK 动态代理的实现 2 | 3 | ### 实现思路 4 | 1、声明一段源码(动态产生代理) 5 | 2、编译源码(JDK Compiler API),产生新的类(代理类) 6 | 3、将这个类 load 到内存中,产生一个新的对象(代理对象) 7 | 4、return 代理对象 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/proxy/dynamic/jdk/Client.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.proxy.dynamic.jdk; 2 | 3 | import com.cipher.pattern.proxy.Car; 4 | import com.cipher.pattern.proxy.Moveable; 5 | 6 | import java.lang.reflect.Proxy; 7 | 8 | /** 9 | * JDK 动态代理测试类 10 | * Created by cipher on 2017/9/6. 11 | */ 12 | public class Client { 13 | 14 | public static void main(String[] args) { 15 | // 记录时间 16 | Moveable carByTime = getTimeProxy(new Car()); 17 | carByTime.move(); 18 | System.out.println("-------------------------"); 19 | // 记录日志、记录时间 20 | Moveable carByLogTime = getLogProxy(getTimeProxy(new Car())); 21 | carByLogTime.move(); 22 | } 23 | 24 | // 获取时间记录的代理 25 | private static Moveable getTimeProxy(Moveable m) { 26 | TimeHandler timeHandler = new TimeHandler(m); 27 | // 传入代理类的类加载器,代理类实现的接口,代理处理器 28 | return (Moveable) Proxy.newProxyInstance(Car.class.getClassLoader(), Car.class.getInterfaces(), timeHandler); 29 | } 30 | 31 | // 获取日志的代理 32 | private static Moveable getLogProxy(Moveable m) { 33 | LogHandler logHandler = new LogHandler(m); 34 | return (Moveable) Proxy.newProxyInstance(Car.class.getClassLoader(), Car.class.getInterfaces(), logHandler); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/proxy/dynamic/jdk/LogHandler.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.proxy.dynamic.jdk; 2 | 3 | import java.lang.reflect.InvocationHandler; 4 | import java.lang.reflect.Method; 5 | 6 | /** 7 | * 日志处理器(实现代理的业务逻辑) 8 | * Created by cipher on 2017/9/6. 9 | */ 10 | public class LogHandler implements InvocationHandler { 11 | 12 | // 被代理对象,不需要知道类型 13 | private Object target; 14 | 15 | public LogHandler(Object target) { 16 | this.target = target; 17 | } 18 | 19 | /** 20 | * @param proxy 生成的代理对象 21 | * @param method 被代理对象的方法 22 | * @param args 方法参数 23 | * @return 方法的返回值 24 | * @throws Throwable 25 | */ 26 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 27 | System.out.println("日志开始......"); 28 | // 执行被代理类的方法 29 | Object o = method.invoke(target); 30 | System.out.println("日志结束......"); 31 | return o; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/proxy/dynamic/jdk/TimeHandler.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.proxy.dynamic.jdk; 2 | 3 | import java.lang.reflect.InvocationHandler; 4 | import java.lang.reflect.Method; 5 | 6 | /** 7 | * 时间记录处理器(实现代理的业务逻辑) 8 | * Created by cipher on 2017/9/6. 9 | */ 10 | public class TimeHandler implements InvocationHandler { 11 | 12 | // 被代理对象,不需要知道类型 13 | private Object target; 14 | 15 | public TimeHandler(Object target) { 16 | this.target = target; 17 | } 18 | 19 | /** 20 | * @param proxy 生成的代理对象 21 | * @param method 被代理对象的方法 22 | * @param args 方法参数 23 | * @return 方法的返回值 24 | * @throws Throwable 25 | */ 26 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 27 | long start = System.currentTimeMillis(); 28 | System.out.println("汽车开始行驶......"); 29 | // 执行被代理类的方法 30 | Object o = method.invoke(target); 31 | long end = System.currentTimeMillis(); 32 | System.out.println("汽车结束行驶......行驶时间:" + (end - start) + "毫秒"); 33 | return o; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/proxy/dynamic/jdk/readme.md: -------------------------------------------------------------------------------- 1 | ## JDK 动态代理 2 | 3 | 只能代理实现了接口的类,没有实现接口的类不能使用 JDK 的动态代理。 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/proxy/dynamic/readme.md: -------------------------------------------------------------------------------- 1 | ## 动态代理实现智能代理 2 | 3 | 代理对象在实现业务逻辑的时候,并不知道要代理的对象是什么。在调用时才传入被代理的对象。 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/proxy/readme.md: -------------------------------------------------------------------------------- 1 | ## 代理模式 2 | 3 | ### 概念 4 | 为其他对象提供一种代理,以控制对这个对象的访问。代理对象起到中介的作用,可以去掉功能服务 5 | 或增加额外的服务。 6 | 7 | 例如:火车票代售处是火车站的代理,它没有退票服务,但是有电话预约等服务。 8 | 9 | ### 分类 10 | 11 | #### 远程代理 12 | 为不同地理位置的对象,提供局域网代表对象。例如远程监控。 13 | 14 | #### 虚拟代理 15 | 根据需要,将一个资源消耗很大的对象进行延迟,真正需要的时候才创建。例如:网页渲染时,使用 16 | 虚拟的图片代替真实的图片,当真实图片加载完成后才显示。 17 | 18 | #### 保护代理 19 | 控制对一个对象的访问权限。例如权限控制。 20 | 21 | #### 智能代理 22 | 提供对目标对象额外的服务。 23 | 24 | 25 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/proxy/statics/CarByExtend.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.proxy.statics; 2 | 3 | import com.cipher.pattern.proxy.Car; 4 | 5 | /** 6 | * 继承方式实现代理(不推荐) 7 | * Created by cipher on 2017/9/6. 8 | */ 9 | public class CarByExtend extends Car { 10 | 11 | @Override 12 | public void move() { 13 | long start = System.currentTimeMillis(); 14 | System.out.println("汽车开始行驶......"); 15 | super.move(); 16 | long end = System.currentTimeMillis(); 17 | System.out.println("汽车结束行驶......行驶时间:" + (end - start) + "毫秒"); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/proxy/statics/CarLogProxy.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.proxy.statics; 2 | 3 | import com.cipher.pattern.proxy.Moveable; 4 | 5 | /** 6 | * 聚合方式实现日志代理 7 | * Created by cipher on 2017/9/6. 8 | */ 9 | public class CarLogProxy implements Moveable { 10 | 11 | private Moveable moveable; 12 | 13 | public CarLogProxy(Moveable moveable) { 14 | this.moveable = moveable; 15 | } 16 | 17 | public void move() { 18 | System.out.println("日志开始......"); 19 | moveable.move(); 20 | System.out.println("日志结束......"); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/proxy/statics/CarTimeProxy.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.proxy.statics; 2 | 3 | import com.cipher.pattern.proxy.Moveable; 4 | 5 | /** 6 | * 聚合方式实现时间代理 7 | * Created by cipher on 2017/9/6. 8 | */ 9 | public class CarTimeProxy implements Moveable { 10 | 11 | private Moveable moveable; 12 | 13 | public CarTimeProxy(Moveable moveable) { 14 | this.moveable = moveable; 15 | } 16 | 17 | public void move() { 18 | long start = System.currentTimeMillis(); 19 | System.out.println("汽车开始行驶......"); 20 | moveable.move(); 21 | long end = System.currentTimeMillis(); 22 | System.out.println("汽车结束行驶......行驶时间:" + (end - start) + "毫秒"); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/proxy/statics/Client.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.proxy.statics; 2 | 3 | import com.cipher.pattern.proxy.Car; 4 | import com.cipher.pattern.proxy.Moveable; 5 | 6 | /** 7 | * 静态代理测试类 8 | * Created by cipher on 2017/9/6. 9 | */ 10 | public class Client { 11 | 12 | public static void main(String[] args) { 13 | // 继承方式实现代理 14 | Moveable carByExtend = new CarByExtend(); 15 | carByExtend.move(); 16 | System.out.println("-----------------"); 17 | // 聚合方式实现时间代理 18 | Moveable carTimeProxy = new CarTimeProxy(new Car()); 19 | carTimeProxy.move(); 20 | System.out.println("-----------------"); 21 | // 聚合方式实现日志代理 22 | Moveable carLogProxy = new CarLogProxy(new Car()); 23 | carLogProxy.move(); 24 | System.out.println("-----------------"); 25 | // 聚合方式实现时间、日志代理 26 | Moveable carTimeLogProxy = new CarTimeProxy(new CarLogProxy(new Car())); 27 | carTimeLogProxy.move(); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/proxy/statics/readme.md: -------------------------------------------------------------------------------- 1 | ## 静态代理实现智能代理 2 | 3 | 代理和被代理的对象在代理之前是确定的。他们都实现相同的接口或者继承相同的抽象类。 4 | 5 | ### 场景 6 | 有一辆车,它有一个行驶的方法。通过代理,为这辆车增加一个记录行驶时间的方法。 7 | 8 | ### 问题 9 | 如果代理对象一多,代理类也会相应的增多。 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/readme.md: -------------------------------------------------------------------------------- 1 | ## 设计模式 2 | 是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。 3 | 4 | ### 目的 5 | 使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/singleton/HungrySingleton.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.singleton; 2 | 3 | /** 4 | * 饿汉单例模式 5 | * Created by cipher on 2017/9/5. 6 | */ 7 | public class HungrySingleton { 8 | 9 | // 私有化默认的构造方法,防止外界直接创建实例 10 | private HungrySingleton() { 11 | } 12 | 13 | // 创建类的唯一实例,类加载时创建实例 14 | private static HungrySingleton instance = new HungrySingleton(); 15 | 16 | // 提供外界获取实例 17 | public static HungrySingleton getInstance() { 18 | return instance; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/singleton/LazySingleton.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.singleton; 2 | 3 | /** 4 | * 懒汉单例模式 5 | * Created by cipher on 2017/9/5. 6 | */ 7 | public class LazySingleton { 8 | 9 | // 私有化默认的构造方法,防止外界直接创建实例 10 | private LazySingleton() { 11 | } 12 | 13 | // 声明类的唯一实例,初始化为null 14 | private static LazySingleton instance = null; 15 | 16 | // 提供外界获取实例 17 | public static LazySingleton getInstance() { 18 | // 被调用时创建实例 19 | if (instance == null) { 20 | System.out.println("创建懒汉单例模式实例"); 21 | instance = new LazySingleton(); 22 | } 23 | return instance; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/singleton/Test.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.singleton; 2 | 3 | /** 4 | * 单例模式测试 5 | * Created by cipher on 2017/9/5. 6 | */ 7 | public class Test { 8 | 9 | public static void main(String[] args) { 10 | // 饿汉 11 | HungrySingleton h1 = HungrySingleton.getInstance(); 12 | HungrySingleton h2 = HungrySingleton.getInstance(); 13 | System.out.println(h1 == h2); 14 | 15 | // 懒汉 16 | LazySingleton l1 = LazySingleton.getInstance(); 17 | LazySingleton l2 = LazySingleton.getInstance(); 18 | System.out.println(l1 == l2); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/singleton/readme.md: -------------------------------------------------------------------------------- 1 | ## 单例模式 2 | 3 | ### 作用 4 | 保证整个应用中某个实例有且只有一个。 5 | 6 | ### 应用场合 7 | 有些对象我们只需要一个,比如: 8 | - 配置文件 9 | - 工具类 10 | - 线程池 11 | - 缓存 12 | - 日志对象 13 | 14 | 如果创造出多个实例,就会导致许多问题,比如占用过多资源,不一致的结果等。 15 | 16 | ### 类型 17 | 饿汉模式:特点是加载类时比较慢,但运行时获取对象的速度比较快,线程安全。 18 | 19 | 懒汉模式:特点是加载类时比较快,但运行时获取对象的速度比较慢,线程不安全。 20 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/strategy/Client.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.strategy; 2 | 3 | /** 4 | * 策略模式测试类 5 | * Created by cipher on 2017/9/12. 6 | */ 7 | public class Client { 8 | 9 | public static void main(String[] args) { 10 | Duck mallardDuck = new MallardDuck(); 11 | mallardDuck.display(); 12 | mallardDuck.quack(); 13 | mallardDuck.fly(); 14 | System.out.println("------------------------------"); 15 | Duck redheadDuck = new RedheadDuck(); 16 | redheadDuck.display(); 17 | redheadDuck.quack(); 18 | redheadDuck.fly(); 19 | System.out.println("------------------------------"); 20 | Duck rubberDuck = new RubberDuck(); 21 | rubberDuck.display(); 22 | rubberDuck.quack(); 23 | rubberDuck.fly(); 24 | System.out.println("------------------------------"); 25 | Duck spaceDuck = new SpaceDuck(); 26 | spaceDuck.display(); 27 | spaceDuck.quack(); 28 | spaceDuck.fly(); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/strategy/Duck.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.strategy; 2 | 3 | /** 4 | * 抽象类:所有鸭子都继承此类 5 | * 抽象了鸭子的行为:显示和鸣叫 6 | * Created by cipher on 2017/9/12. 7 | */ 8 | public abstract class Duck { 9 | 10 | // 飞行策略接口 11 | private FlyingStrategy flyingStrategy; 12 | 13 | // 子类注入飞行接口实现类 14 | public void setFlyingStrategy(FlyingStrategy flyingStrategy) { 15 | this.flyingStrategy = flyingStrategy; 16 | } 17 | 18 | /** 19 | * 鸭子飞行,通过策略接口实现 20 | */ 21 | public void fly() { 22 | this.flyingStrategy.performFly(); 23 | } 24 | 25 | /** 26 | * 鸭子发出叫声 27 | * 通用行为,由超类实现 28 | */ 29 | public void quack() { 30 | System.out.println("嘎嘎嘎~"); 31 | } 32 | 33 | /** 34 | * 显示鸭子的外观 35 | * 鸭子的外观歌不相同,声明为 abstract,由子类实现 36 | */ 37 | public abstract void display(); 38 | 39 | } 40 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/strategy/FlyingStrategy.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.strategy; 2 | 3 | /** 4 | * 策略接口:飞行策略 5 | * Created by cipher on 2017/9/12. 6 | */ 7 | public interface FlyingStrategy { 8 | 9 | /** 10 | * 执行飞行动作 11 | */ 12 | void performFly(); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/strategy/MallardDuck.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.strategy; 2 | 3 | import com.cipher.pattern.strategy.impl.FlyWithWing; 4 | 5 | /** 6 | * 绿头鸭,具体的鸭子 7 | * Created by cipher on 2017/9/12. 8 | */ 9 | public class MallardDuck extends Duck { 10 | 11 | public MallardDuck() { 12 | super.setFlyingStrategy(new FlyWithWing()); 13 | } 14 | 15 | public void display() { 16 | System.out.println("我的脖子是绿色的"); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/strategy/RedheadDuck.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.strategy; 2 | 3 | import com.cipher.pattern.strategy.impl.FlyWithWing; 4 | 5 | /** 6 | * 红头鸭,具体的鸭子 7 | * Created by cipher on 2017/9/12. 8 | */ 9 | public class RedheadDuck extends Duck { 10 | 11 | public RedheadDuck() { 12 | super.setFlyingStrategy(new FlyWithWing()); 13 | } 14 | 15 | public void display() { 16 | System.out.println("我的头是红色的"); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/strategy/RubberDuck.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.strategy; 2 | 3 | import com.cipher.pattern.strategy.impl.FlyNoWay; 4 | 5 | /** 6 | * 橡皮鸭:具体的鸭子 7 | * Created by cipher on 2017/9/12. 8 | */ 9 | public class RubberDuck extends Duck { 10 | 11 | public RubberDuck() { 12 | super.setFlyingStrategy(new FlyNoWay()); 13 | } 14 | 15 | public void display() { 16 | System.out.println("我是橡皮鸭"); 17 | } 18 | 19 | // 覆盖父类方法 20 | public void quack() { 21 | System.out.println("嘎~嘎~嘎~"); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/strategy/SpaceDuck.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.strategy; 2 | 3 | import com.cipher.pattern.strategy.impl.FlyWithRocket; 4 | 5 | /** 6 | * 太空鸭:具体的鸭子 7 | * Created by cipher on 2017/9/12. 8 | */ 9 | public class SpaceDuck extends Duck { 10 | 11 | public SpaceDuck() { 12 | super.setFlyingStrategy(new FlyWithRocket()); 13 | } 14 | 15 | public void display() { 16 | System.out.println("我是太空鸭"); 17 | } 18 | 19 | // 覆盖父类方法 20 | public void quack() { 21 | System.out.println("我用无线电与你通信~"); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/strategy/impl/FlyNoWay.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.strategy.impl; 2 | 3 | import com.cipher.pattern.strategy.FlyingStrategy; 4 | 5 | /** 6 | * 飞行接口实现类 7 | * Created by cipher on 2017/9/12. 8 | */ 9 | public class FlyNoWay implements FlyingStrategy { 10 | 11 | public void performFly() { 12 | System.out.println("我不会飞!"); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/strategy/impl/FlyWithRocket.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.strategy.impl; 2 | 3 | import com.cipher.pattern.strategy.FlyingStrategy; 4 | 5 | /** 6 | * 飞行接口实现类 7 | * Created by cipher on 2017/9/12. 8 | */ 9 | public class FlyWithRocket implements FlyingStrategy { 10 | 11 | public void performFly() { 12 | System.out.println("用火箭飞行~"); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/strategy/impl/FlyWithWing.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.strategy.impl; 2 | 3 | import com.cipher.pattern.strategy.FlyingStrategy; 4 | 5 | /** 6 | * 飞行接口实现类 7 | * Created by cipher on 2017/9/12. 8 | */ 9 | public class FlyWithWing implements FlyingStrategy { 10 | 11 | public void performFly() { 12 | System.out.println("振翅高飞~"); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/strategy/readme.md: -------------------------------------------------------------------------------- 1 | ## 策略模式 2 | 3 | ### 概念 4 | 策略模式将可变的部分从程序中抽象分离成算法接口,在该接口下分别封装一系列算法实现构成 5 | 算法家族,并使他们可以相互替换,从而使客户端程序独立于算法的改变。 6 | 7 | 多用组合,少用继承 8 | 9 | 组合:在类中增加一个私有域,引用另一个已有类的事例,通过调用引用事例的方法从而获得新的功能,这种设计就称作组合(复合)。 10 | 11 | ### 实现 12 | - 通过分离变化得出策略接口 13 | - 提供接口不同的实现类 14 | - 将接口组合到目标类中 15 | 16 | ### 优点 17 | - 使用了组合,使架构更加灵活,符合开闭原则 18 | - 更好的代码复用性 19 | - 消除大量的条件语句 20 | 21 | ### 缺点 22 | - 客户代码需要了解每个策略实现的细节 23 | - 增加了对象的数目 24 | 25 | ### 适用场景 26 | - 许多相关的类仅仅是行为差异 27 | - 运行时选取不同的算法变体 28 | - 通过条件语句在多个分支中选取其一 29 | 30 | ### 例子背景-鸭子应用 31 | 已有功能: 32 | - 鸣叫 33 | - 显示 34 | 35 | 新功能: 36 | - 飞行的能力 37 | - 更多的鸭子类型 38 | - 每六个月发布一款产品 -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/template/Coffee.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.template; 2 | 3 | 4 | /** 5 | * @Author: CipherCui 6 | * @Description: 7 | * @Date: Created in 16:40 2018/11/8 8 | */ 9 | public class Coffee extends RefreshBeverage { 10 | 11 | @Override 12 | protected void brew() { 13 | System.out.println("用沸水冲泡咖啡"); 14 | } 15 | 16 | @Override 17 | protected void addCondiments() { 18 | System.out.println("加入糖和牛奶"); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/template/Main.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.template; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: 6 | * @Date: Created in 16:42 2018/11/8 7 | */ 8 | public class Main { 9 | 10 | public static void main(String[] args) { 11 | RefreshBeverage coffee = new Coffee(); 12 | coffee.prepareBeverageTemplate(); 13 | System.out.println(); 14 | RefreshBeverage tea = new Tea(); 15 | tea.prepareBeverageTemplate(); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/template/RefreshBeverage.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.template; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: 6 | * @Date: Created in 16:33 2018/11/8 7 | */ 8 | public abstract class RefreshBeverage { 9 | 10 | public final void prepareBeverageTemplate() { 11 | // 将水煮沸 12 | boilWater(); 13 | // 泡制饮料 14 | brew(); 15 | // 将饮料倒入杯中 16 | pourInCup(); 17 | if (isCondiments()) { 18 | // 加入调味料 19 | addCondiments(); 20 | } 21 | } 22 | 23 | protected boolean isCondiments() { 24 | return true; 25 | } 26 | 27 | private void boilWater() { 28 | System.out.println("将水煮沸"); 29 | } 30 | 31 | protected abstract void brew(); 32 | 33 | private void pourInCup() { 34 | System.out.println("将饮料倒入杯中"); 35 | } 36 | 37 | protected void addCondiments() { 38 | 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/template/Tea.java: -------------------------------------------------------------------------------- 1 | package com.cipher.pattern.template; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: 6 | * @Date: Created in 16:42 2018/11/8 7 | */ 8 | public class Tea extends RefreshBeverage { 9 | 10 | @Override 11 | protected void brew() { 12 | System.out.println("用80度的热水浸泡茶叶5分钟"); 13 | } 14 | 15 | @Override 16 | protected boolean isCondiments() { 17 | return false; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/pattern/template/readme.md: -------------------------------------------------------------------------------- 1 | ## 模板方法模式 2 | 3 | ### 概念 4 | 定义了一个操作中的算法骨架,而将一些步骤延迟到子类中实现,使得子类在不改变一个算法结构的同时,能重新定义 5 | 算法的某些特定步骤。 6 | 7 | ### 实现要素 8 | 准备一个抽象类,将部分逻辑以具体方法的形式实现,然后声明一些抽象方法交由子类实现剩余逻辑,用钩子方法给予子类 9 | 更大的灵活性。最后将方法汇总构成一个不可改变的(final)模板方法。 10 | 11 | ### 适用场景 12 | 13 | - 算法或操作遵循相似的逻辑 14 | - 重构时(把相同的代码抽取到父类中) 15 | - 重要、复杂的算法,核心算法设计为模板算法 16 | 17 | ### 优点 18 | 19 | - 封装性好 20 | - 复用性好 21 | - 屏蔽细节 22 | - 便于维护 23 | 24 | ### 缺点 25 | 26 | - 继承 -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/redis_algorithm/readme.md: -------------------------------------------------------------------------------- 1 | ## redis算法java实现 -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/redis_algorithm/skiplist/Constant.java: -------------------------------------------------------------------------------- 1 | package com.cipher.redis_algorithm.skiplist; 2 | 3 | /** 4 | * 跳跃表用到的各种常量 5 | * 6 | * @author cipher 7 | */ 8 | public class Constant { 9 | 10 | /** 11 | * 节点层高最大值 12 | */ 13 | public static final int ZSKIPLIST_MAXLEVEL = 64; 14 | 15 | /** 16 | * 控制节点层高的概率,当 p=0.25 时,跳跃表的期望层高是 1/(1-0.25)≈1.33 17 | */ 18 | public static final float ZSKIPLIST_P = 0.25f; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/redis_algorithm/skiplist/Test.java: -------------------------------------------------------------------------------- 1 | package com.cipher.redis_algorithm.skiplist; 2 | 3 | public class Test { 4 | 5 | public static void main(String[] args) { 6 | Zskiplist zsl = Zskiplist.zslCreate(); 7 | ZskiplistOp.zslInsert(zsl, 31, "C"); 8 | ZskiplistOp.zslInsert(zsl, 41, "D"); 9 | ZskiplistOp.zslInsert(zsl, 21, "B"); 10 | ZskiplistOp.zslInsert(zsl, 1, "A"); 11 | System.out.println(); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/spi/ChineseDemoServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.cipher.spi; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: 6 | * @Date: Created in 13:39 2018/9/12 7 | */ 8 | public class ChineseDemoServiceImpl implements DemoService { 9 | 10 | @Override 11 | public String sayHi(String msg) { 12 | return "你好, " + msg; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/spi/DemoService.java: -------------------------------------------------------------------------------- 1 | package com.cipher.spi; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: 6 | * @Date: Created in 13:37 2018/9/12 7 | */ 8 | public interface DemoService { 9 | 10 | String sayHi(String msg); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/spi/EnglishDemoServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.cipher.spi; 2 | 3 | /** 4 | * @Author: CipherCui 5 | * @Description: 6 | * @Date: Created in 13:38 2018/9/12 7 | */ 8 | public class EnglishDemoServiceImpl implements DemoService { 9 | 10 | @Override 11 | public String sayHi(String msg) { 12 | return "Hello, " + msg; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/spi/Main.java: -------------------------------------------------------------------------------- 1 | package com.cipher.spi; 2 | 3 | import java.util.ServiceLoader; 4 | 5 | /** 6 | * @Author: CipherCui 7 | * @Description: 8 | * @Date: Created in 13:41 2018/9/12 9 | */ 10 | public class Main { 11 | 12 | public static void main(String[] args) { 13 | ServiceLoader serviceLoader = ServiceLoader.load(DemoService.class); 14 | for (DemoService demoService : serviceLoader) { 15 | System.out.println(demoService.getClass().getName() + " >>>>>> " + demoService.sayHi("World")); 16 | } 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/test/Test.java: -------------------------------------------------------------------------------- 1 | package com.cipher.test; 2 | 3 | public class Test { 4 | 5 | public static void main(String[] args) throws Exception { 6 | } 7 | 8 | } 9 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/threading/DelayExecutor.java: -------------------------------------------------------------------------------- 1 | package com.cipher.threading; 2 | 3 | import java.util.concurrent.Executors; 4 | import java.util.concurrent.ScheduledExecutorService; 5 | import java.util.concurrent.TimeUnit; 6 | 7 | /** 8 | * @Author: CipherCui 9 | * @Description: 从 dubbo 源码抄过来的延时调度执行器 10 | * @Date: Created in 9:51 2018/9/7 11 | */ 12 | public class DelayExecutor { 13 | 14 | private static final ScheduledExecutorService delayExportExecutor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("DemoDelayExporter", true)); 15 | 16 | public static void main(String[] args) throws InterruptedException { 17 | delayExportExecutor.schedule(() -> { 18 | System.out.println(111); 19 | }, 1000, TimeUnit.MILLISECONDS); 20 | System.out.println(222); 21 | Thread.sleep(5000); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/threading/MyRunnable.java: -------------------------------------------------------------------------------- 1 | package com.cipher.threading; 2 | 3 | /** 4 | * 创建10个线程,每个线程都打印从0到99这100个数字,希望线程之间不会出现交叉乱序打印,而是顺序地打印。 5 | */ 6 | public class MyRunnable implements Runnable { 7 | 8 | private static Object lock = new Object(); 9 | 10 | public void run() { 11 | synchronized (lock) { 12 | for (int i = 0; i <= 99; i++) { 13 | System.out.println(i); 14 | } 15 | } 16 | } 17 | 18 | public static void main(String[] args) { 19 | for (int i = 0; i <= 10; i++) { 20 | new Thread(new MyRunnable()).start(); 21 | } 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /sandbox/src/main/java/com/cipher/threading/readme.md: -------------------------------------------------------------------------------- 1 | ## 多线程 -------------------------------------------------------------------------------- /sandbox/src/main/resources/META-INF/services/com.cipher.spi.DemoService: -------------------------------------------------------------------------------- 1 | #English implementation 2 | com.cipher.spi.EnglishDemoServiceImpl 3 | 4 | #Chinese implementation 5 | com.cipher.spi.ChineseDemoServiceImpl --------------------------------------------------------------------------------