diff --git a/src/com/blankj/custom/AnagramCheck.java b/src/com/blankj/custom/AnagramCheck.java new file mode 100644 index 00000000..4a7fbd8f --- /dev/null +++ b/src/com/blankj/custom/AnagramCheck.java @@ -0,0 +1,45 @@ +package com.blankj.custom; + +import java.util.Arrays; + +public class AnagramCheck { + public static void main(String[] args) { + String s1 = "abcd"; + String s2 = "dcba"; + System.out.println(isAnagram3(s1, s2)); + } + + public static boolean isAnagram(String word, String anagram) { + StringBuilder sb = new StringBuilder(word); + sb.reverse();//将str倒置的方法 + String newStr = new String(sb); + return anagram.equals(newStr); + } + + + public static boolean iAnagram2(String word, String anagram) { + //默认长度>1 + char[] charFromWord = word.toCharArray(); + char[] charFromAnagram = anagram.toCharArray(); + Arrays.sort(charFromWord); + Arrays.sort(charFromAnagram); + return !word.equals(anagram) && Arrays.equals(charFromWord, charFromAnagram); + } + + public static boolean isAnagram3(String word, String anagram) { + if (word.length() != anagram.length() || word.equals(anagram)) { + return false; + } + char[] chars = word.toCharArray(); + for (char c : chars) { + int index = anagram.indexOf(c); + if (index != -1) { + anagram = anagram.substring(0, index) + anagram.substring(index + 1, anagram.length()); + } else { + return false; + } + } + return anagram.isEmpty(); + } + +} diff --git a/src/com/blankj/custom/BitWiseExample.java b/src/com/blankj/custom/BitWiseExample.java new file mode 100644 index 00000000..155878af --- /dev/null +++ b/src/com/blankj/custom/BitWiseExample.java @@ -0,0 +1,73 @@ +package com.blankj.custom; + +//https://www.mkyong.com/java/java-convert-ip-address-to-decimal-number/ +//https://www.mkyong.com/java/java-and-0xff-example/?utm_source=mkyong&utm_medium=author&utm_campaign=related-post&utm_content=0 + +//http://blog.csdn.net/tinna_zhang/article/details/44414747 +//0xFF (十进制1) +//二进制码:00000000 00000000 00000000 11111111 +//由于0xff最低的8位是1,因此number中低8位中的&之后,如果原来是1,结果还是1,原来是0,结果位还 +//是0.高于8位的,0xff都是0,所以无论是0还是1,结果都是0. + +public class BitWiseExample { + + public static void main(String[] args) { + + BitWiseExample obj = new BitWiseExample(); + long ipAddressInLong = obj.ipToLong("192.168.1.2"); + System.out.println(ipAddressInLong); + + String binary = Long.toBinaryString(ipAddressInLong); + printPrettyBinary(binary); + + String ipAddressInString = obj.longToIp(ipAddressInLong); + System.out.println(ipAddressInString); + + int i = 12315; + System.out.println(Integer.toBinaryString(i)); + System.out.println(i >> 2); + System.out.println(binaryToInt(Integer.toBinaryString(i))); + + } + + public long ipToLong(String ipAddress) { + String[] addrArray = ipAddress.split("\\."); + long num = 0; + for (int i = 0; i < addrArray.length; i++) { + int power = 3 - i; + // 1. (192 % 256) * 256 pow 3 + // 2. (168 % 256) * 256 pow 2 + // 3. (2 % 256) * 256 pow 1 + // 4. (1 % 256) * 256 pow 0 + num += ((Integer.parseInt(addrArray[i]) % 256 * Math.pow(256, power))); + + } + + return num; + } + + public String longToIp(long i) { + return ((i >> 24) & 0xFF) + "." + ((i >> 16) & 0xFF) + "." + ((i >> 8) & 0xFF) + "." + (i & 0xFF); + } + + //print pretty binary code, padding left zero + private static void printPrettyBinary(String binary) { + + String s1 = String.format("%32s", binary).replace(' ', '0'); + System.out.format("%8s %8s %8s %8s %n", + s1.substring(0, 8), s1.substring(8, 16), + s1.substring(16, 24), s1.substring(24, 32)); + } + + public static int binaryToInt(String binaryString) { + int intNumber = 0; + for (int i = 0; i < binaryString.length(); i++) { +// int t = binaryString.length() - i; +// System.out.println((t - 1) + " " + (t)); + if (binaryString.substring(binaryString.length() - i - 1,binaryString.length() - i).equals("1")) { + intNumber += Math.pow(2, i); + } + } + return intNumber; + } +} diff --git a/src/com/blankj/custom/CircleNode.java b/src/com/blankj/custom/CircleNode.java new file mode 100644 index 00000000..e04801c8 --- /dev/null +++ b/src/com/blankj/custom/CircleNode.java @@ -0,0 +1,92 @@ +package com.blankj.custom; + + +import com.blankj.custom.structure.ListNode; + +public class CircleNode { + + //判断是否有环 + public static boolean isLoop(ListNode head) { + ListNode fast = head; + ListNode slow = head; + //如果无环,则fast先走到终点 + //当链表长度为奇数时,fast->Next为空 + //当链表长度为偶数时,fast为空 + + while (fast != null && fast.next != null) { + fast = fast.next.next; + slow = slow.next; + //如果有环,则fast会超过slow一圈 + if (fast == slow) { + break; + } + } + + return fast != null && fast.next != null; + } + + //计算环的长度 + public static int loopLength(ListNode head) { + if (isLoop(head)) return 0; + ListNode fast = head; + ListNode slow = head; + int length = 0; + boolean begin = false; + boolean again = false; + while (fast != null && fast.next != null) { + fast = fast.next.next; + slow = slow.next; + + //超两圈后停止计数,挑出循环 + if (fast == slow && again) { + break; + } + + //超一圈后开始计数 + if (fast == slow) { + begin = true; + again = true; + } + + //计数 + if (begin) + ++length; + + } + return length; + } + + //求出环的入口点 + ListNode findLoopEntrance(ListNode head) { + ListNode fast = head; + ListNode slow = head; + + while (fast != null && fast.next != null) { + fast = fast.next.next; + slow = slow.next; + //如果有环,则fast会超过slow一圈 + if (fast == slow) { + break; + } + } + + if (fast == null || fast.next == null) return null; + slow = head; +// 碰撞点p到连接点的距离=头指针到连接点的距离,因此,分别从碰撞点、头指针开始走,相遇的那个点就是连接点 + while (slow != fast) { + slow = slow.next; + fast = fast.next; + } + return slow; + } + + // 4.如何判断两个链表(不带环)是否相交?将其中的一个链表首尾相连,然后判断另一个链表是否带环即可。 + boolean checkCross(ListNode listNode1, ListNode listNode2) { + ListNode listNode = listNode1; + while (listNode1.next != null) { + listNode = listNode.next; + } + listNode.next = listNode1; + return isLoop(listNode2); + } +} diff --git a/src/com/blankj/custom/ClassLoaderTest.java b/src/com/blankj/custom/ClassLoaderTest.java new file mode 100644 index 00000000..5dc3f8ac --- /dev/null +++ b/src/com/blankj/custom/ClassLoaderTest.java @@ -0,0 +1,32 @@ +package com.blankj.custom; + + +//https://www.jianshu.com/p/5f468de3b806 + +public class ClassLoaderTest { + + public static void main(String[] args) { + System.out.println(A.j); +// System.out.println(A.i); + } + + static class A { + + static int i = 2; + + //可见类 A 是已经被准备过了,但是尚未初始化. +// 准备阶段负责创建类静态字段,并把它初始化成默认值。这里的初始化, +// 并不是调用代码的静态字段赋值语句和静态代码块,而是把每个静态字段初始化成 JVM 给定的初始值 +// 当然也有例外,字段被认为是 constant variable 时,也会在准备阶段被赋值 + + static final int j = 3; + + static final int k; + + static { + i = 3; + k = 3; + System.out.println("hello world"); + } + } +} diff --git a/src/com/blankj/custom/DupInArray.java b/src/com/blankj/custom/DupInArray.java new file mode 100644 index 00000000..9eb74ce5 --- /dev/null +++ b/src/com/blankj/custom/DupInArray.java @@ -0,0 +1,24 @@ +package com.blankj.custom; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; + +public class DupInArray { + public static void main(String[] args) { + String[] array = new String[]{"a","a","b","a","c","c"}; + System.out.println(Arrays.toString(getDupElement(array).toArray())); + } + + public static List getDupElement(String[] array) { + HashSet hashSet = new HashSet(); + List dupList = new ArrayList<>(); + for (String name : array) { + if (!hashSet.add(name)) { + if(!dupList.contains(name)) dupList.add(name); + } + } + return dupList; + } +} diff --git a/src/com/blankj/custom/KMP.java b/src/com/blankj/custom/KMP.java new file mode 100644 index 00000000..49ef75b2 --- /dev/null +++ b/src/com/blankj/custom/KMP.java @@ -0,0 +1,60 @@ +package com.blankj.custom; + +import java.util.Arrays; + +public class KMP { +// http://blog.csdn.net/v_july_v/article/details/7041827 +// http://blog.csdn.net/christ1750/article/details/51259425 + +// 失配时,模式串向右移动的位数为:已匹配字符数 - 失配字符的上一位字符所对应的最大长度值 + +// 把next 数组跟之前求得的最大长度表对比后,不难发现,next 数组相当于“最大长度值” 整体向右移动一位,然后初始值赋为-1。 +// 意识到了这一点,你会惊呼原来next 数组的求解竟然如此简单:就是找最大对称长度的前缀后缀,然后整体右移一位,初值赋为-1( +// 当然,你也可以直接计算某个字符对应的next值,就是看这个字符之前的字符串中有多大长度的相同前缀后缀)。 + +// 失配时,模式串向右移动的位数为:失配字符所在位置 - 失配字符对应的next 值 + + public static int[] kmpnext(String dest) { +// String a = "baba"; [0,0,1,2] + int[] next = new int[dest.length()]; + next[0] = 0; + for (int i = 1, j = 0; i < dest.length(); i++) { + while (j > 0 && dest.charAt(j) != dest.charAt(i)) { + j = next[j - 1]; + System.out.println("j1= " + j + " i1= " + i); + } + if (dest.charAt(i) == dest.charAt(j)) { + j++; + } + next[i] = j; + } + return next; + } + + public static int kmp(String str, String dest, int[] next) {//str文本串 dest 模式串 + for (int i = 0, j = 0; i < str.length(); i++) { + while (j > 0 && str.charAt(i) != dest.charAt(j)) { + j = next[j - 1]; + System.out.println("j= " + j + " i= " + i); + } + if (str.charAt(i) == dest.charAt(j)) { + j++; + } + if (j == dest.length()) { + return i - j + 1; + } + } + return 0; + } + + public static void main(String[] args) { + //next 数组确实是只要将各个最大前缀后缀的公共元素的长度值右移一位,且把初值赋为-1 即可 + String a = "abcabcaaf"; + String b = "abcabcabea"; + int[] next = kmpnext(a); + int res = kmp(b, a, next); + + System.out.println("index is: " + res); + System.out.println(Arrays.toString(next)); + } +} diff --git a/src/com/blankj/custom/Permutation.java b/src/com/blankj/custom/Permutation.java new file mode 100644 index 00000000..c9e4909a --- /dev/null +++ b/src/com/blankj/custom/Permutation.java @@ -0,0 +1,36 @@ +package com.blankj.custom; + +import java.util.ArrayList; +import java.util.Arrays; + +public class Permutation { + + public static void main(String[] args) { +// System.out.println(permutation("abcd").length); + System.out.println(Arrays.toString(permutation("abc"))); + } + + private static String[] permutation(String orginal) { + System.out.println("orginal = " + orginal); + ArrayList list = new ArrayList(); + if (orginal.length() == 1) { + System.out.println("跳出递归 " + orginal); + return new String[]{orginal}; + } else { + for (int i = 0; i < orginal.length(); i++) { + String s = orginal.charAt(i) + ""; + System.out.println("s: " + s + " + " + i); + //e.g bc时分别输出c b + String leftS = orginal.substring(0, i) + orginal.substring(i + 1, orginal.length()); + System.out.println("leftS: " + leftS); + //递归 permutation(leftS) + for (String element : permutation(leftS)) { + System.out.println("递归: " + s + " + " + element + " = " + (s + element)); + list.add(s + element); + } + } + System.out.println(Arrays.toString(list.toArray())); + return (String[]) list.toArray(new String[list.size()]); + } + } +} diff --git a/src/com/blankj/custom/QuickSort.java b/src/com/blankj/custom/QuickSort.java new file mode 100644 index 00000000..5aadce22 --- /dev/null +++ b/src/com/blankj/custom/QuickSort.java @@ -0,0 +1,46 @@ +package com.blankj.custom; + +public class QuickSort { + public static void main(String[] args) { + int unsortedArray[] = new int[]{6, 5, 3, 1, 8, 7, 2, 4}; + quickSort(unsortedArray); + System.out.println("After sort: "); + for (int item : unsortedArray) { + System.out.print(item + " "); + } + } + + public static void quickSort2(int[] array, int l, int u) { + for (int item : array) { + System.out.print(item + " "); + } + System.out.println(); + if (l >= u) return; + int pivot = array[l]; + int left = l + 1; + int right = u; + while (left <= right) { + while (left <= right && array[left] < pivot) { + left++; + } + while (left <= right && array[right] >= pivot) { + right--; + } + if (left > right) break; + // swap array[left] with array[right] while left <= right + int temp = array[right]; + array[right] = array[left]; + array[left] = temp; + } + /* swap the smaller with pivot */ + int temp = array[right]; + array[right] = array[l]; + array[l] = temp; + quickSort2(array, l, right - 1); + quickSort2(array, right + 1, u); + } + + public static void quickSort(int[] array) { + quickSort2(array, 0, array.length - 1); + } +} diff --git a/src/com/blankj/custom/Swap.java b/src/com/blankj/custom/Swap.java new file mode 100644 index 00000000..1a7de6e4 --- /dev/null +++ b/src/com/blankj/custom/Swap.java @@ -0,0 +1,12 @@ +package com.blankj.custom; + +public class Swap { + public static void main(String[] args) { + int x = 10; + int y = 20; + x = x ^ y; + y = x ^ y; + x = x ^ y; + System.out.printf("After swapping, 'x': %d, 'y': %d", x, y); + } +} \ No newline at end of file diff --git a/src/com/blankj/custom/anotition/Col.java b/src/com/blankj/custom/anotition/Col.java new file mode 100755 index 00000000..a59c16dc --- /dev/null +++ b/src/com/blankj/custom/anotition/Col.java @@ -0,0 +1,12 @@ +package com.blankj.custom.anotition; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Col { + String name(); +} diff --git a/src/com/blankj/custom/anotition/Main.java b/src/com/blankj/custom/anotition/Main.java new file mode 100755 index 00000000..3144bd97 --- /dev/null +++ b/src/com/blankj/custom/anotition/Main.java @@ -0,0 +1,37 @@ +package com.blankj.custom.anotition; + +import java.lang.reflect.Field; + + +public class Main { + public static void main(String[] args) throws ClassNotFoundException { + String key = "MAJIAXUEYUAN"; + + StringBuffer sb = new StringBuffer(); + sb.append("select "); + // 反射拿到字节码文件 + Class forName = Class.forName("com.blankj.custom.anotition.User"); + + // 拿到成员属性 + Field[] declaredFields = forName.getDeclaredFields(); + + // 遍历属性 + for (int i = 0; i < declaredFields.length; i++) { + // 拿到注解获取name值 + Col col = declaredFields[i].getDeclaredAnnotation(Col.class); + String name = col.name(); + sb.append(name); + if (i == declaredFields.length - 1) { + sb.append(" from "); + } else { + sb.append(" , "); + } + } + Table table = forName.getAnnotation(Table.class); + String name = table.name(); + sb.append(name + " "); + sb.append(" where user_name = '" + key + "'"); + System.out.println(sb.toString()); + // select user_name,user_age from tb_user; + } +} diff --git a/src/com/blankj/custom/anotition/Table.java b/src/com/blankj/custom/anotition/Table.java new file mode 100755 index 00000000..8f99a470 --- /dev/null +++ b/src/com/blankj/custom/anotition/Table.java @@ -0,0 +1,13 @@ +package com.blankj.custom.anotition; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface Table { + // @table(name="") + String name(); +} diff --git a/src/com/blankj/custom/anotition/User.java b/src/com/blankj/custom/anotition/User.java new file mode 100755 index 00000000..3cd65394 --- /dev/null +++ b/src/com/blankj/custom/anotition/User.java @@ -0,0 +1,27 @@ +package com.blankj.custom.anotition; + +@Table(name = "tb_user") +public class User { + + @Col(name = "user_name") + private String userName; + @Col(name = "user_sex") + private String userSex; + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getUserSex() { + return userSex; + } + + public void setUserSex(String userSex) { + this.userSex = userSex; + } + +} diff --git a/src/com/blankj/custom/desingn_pattern/adapter/Adapter.java b/src/com/blankj/custom/desingn_pattern/adapter/Adapter.java new file mode 100644 index 00000000..95efcff1 --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/adapter/Adapter.java @@ -0,0 +1,47 @@ +package com.blankj.custom.desingn_pattern.adapter; + +public class Adapter { +// public class Scanner{ +// public void read(Readable material){ +// material.read(); +// } +// } +// +// public interface Readable{ +// void read(); +// } +// public class TXT implements Readable{ +// ... +// public void read(){ +// //读取txt文件 +// } +// ... +// } +// +// public class HTML{ +// public void toReadableFormat(){ +// //html文件也可以被读取,但是它并没有继承Readable接口,所以无法被Scanner +// 识别 +// } +// } +// +// //这里才是适配器模式 +// public class HTMLAdapter implements Readable{ +// ... +// private HTML html; +// public HTMLAdapter(HTML html){this.html = html} +// public void read(){ +// html.toReadableFormat(); +// } +// ... +// } +// +// //这时候两个文件都可以被读取了 +// public class Test{ +// public static void main(String[] args){ +// Scanner s = new Scanner(); +// s.read(new TXT()); +// s.read(new HTMLAdapter(new HTML())); +// } +// } +} diff --git a/src/com/blankj/custom/desingn_pattern/factory/Benz.java b/src/com/blankj/custom/desingn_pattern/factory/Benz.java new file mode 100755 index 00000000..45b26550 --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/factory/Benz.java @@ -0,0 +1,10 @@ +package com.blankj.custom.desingn_pattern.factory; + +public class Benz implements Car { + + @Override + public void create() { + System.out.println("码家学院的Benz生产成功。"); + } + +} diff --git a/src/com/blankj/custom/desingn_pattern/factory/BenzFactory.java b/src/com/blankj/custom/desingn_pattern/factory/BenzFactory.java new file mode 100755 index 00000000..b9f27039 --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/factory/BenzFactory.java @@ -0,0 +1,7 @@ +package com.blankj.custom.desingn_pattern.factory; + +public interface BenzFactory { + static Car createCar() { + return new Benz(); + } +} diff --git a/src/com/blankj/custom/desingn_pattern/factory/Bmw.java b/src/com/blankj/custom/desingn_pattern/factory/Bmw.java new file mode 100755 index 00000000..478f67f1 --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/factory/Bmw.java @@ -0,0 +1,10 @@ +package com.blankj.custom.desingn_pattern.factory; + +public class Bmw implements Car{ + + @Override + public void create() { + System.out.println("码家学院的BMW生产成功。"); + } + +} diff --git a/src/com/blankj/custom/desingn_pattern/factory/BmwFactory.java b/src/com/blankj/custom/desingn_pattern/factory/BmwFactory.java new file mode 100755 index 00000000..af4aff6f --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/factory/BmwFactory.java @@ -0,0 +1,7 @@ +package com.blankj.custom.desingn_pattern.factory; + +public interface BmwFactory { + static Car createCar() { + return new Bmw(); + } +} diff --git a/src/com/blankj/custom/desingn_pattern/factory/Car.java b/src/com/blankj/custom/desingn_pattern/factory/Car.java new file mode 100755 index 00000000..77eb97f1 --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/factory/Car.java @@ -0,0 +1,5 @@ +package com.blankj.custom.desingn_pattern.factory; + +public interface Car { + void create(); +} diff --git a/src/com/blankj/custom/desingn_pattern/factory/Main.java b/src/com/blankj/custom/desingn_pattern/factory/Main.java new file mode 100755 index 00000000..428b89de --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/factory/Main.java @@ -0,0 +1,12 @@ +package com.blankj.custom.desingn_pattern.factory; + +public class Main { + public static void main(String[] args) { + Car bmw = BmwFactory.createCar(); + Car benz = BenzFactory.createCar(); + + bmw.create(); + benz.create(); + } + +} diff --git a/src/com/blankj/custom/desingn_pattern/observerable/Observer.java b/src/com/blankj/custom/desingn_pattern/observerable/Observer.java new file mode 100644 index 00000000..f5a535a4 --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/observerable/Observer.java @@ -0,0 +1,11 @@ +package com.blankj.custom.desingn_pattern.observerable; + +/*** + * 抽象观察者 + * 定义了一个update()方法,当被观察者调用notifyObservers()方法时,观察者的update()方法会被回调。 + * @author jstao + * + */ +public interface Observer { + void update(String message); +} diff --git a/src/com/blankj/custom/desingn_pattern/observerable/Observerable.java b/src/com/blankj/custom/desingn_pattern/observerable/Observerable.java new file mode 100644 index 00000000..eb49338e --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/observerable/Observerable.java @@ -0,0 +1,15 @@ +package com.blankj.custom.desingn_pattern.observerable; + +/*** + * 抽象被观察者接口 + * 声明了添加、删除、通知观察者方法 + * @author jstao + * + */ +public interface Observerable { + + void registerObserver(Observer o); + void removeObserver(Observer o); + void notifyObserver(); + +} diff --git a/src/com/blankj/custom/desingn_pattern/observerable/Test.java b/src/com/blankj/custom/desingn_pattern/observerable/Test.java new file mode 100644 index 00000000..ada8ee10 --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/observerable/Test.java @@ -0,0 +1,22 @@ +package com.blankj.custom.desingn_pattern.observerable; + +public class Test { + + public static void main(String[] args) { + WechatServer server = new WechatServer(); + + Observer userZhang = new User("ZhangSan"); + Observer userLi = new User("LiSi"); + Observer userWang = new User("WangWu"); + + server.registerObserver(userZhang); + server.registerObserver(userLi); + server.registerObserver(userWang); + server.setInfomation("PHP是世界上最好用的语言!"); + + System.out.println("----------------------------------------------"); + server.removeObserver(userZhang); + server.setInfomation("JAVA是世界上最好用的语言!"); + + } +} diff --git a/src/com/blankj/custom/desingn_pattern/observerable/User.java b/src/com/blankj/custom/desingn_pattern/observerable/User.java new file mode 100644 index 00000000..17f63535 --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/observerable/User.java @@ -0,0 +1,20 @@ +package com.blankj.custom.desingn_pattern.observerable; + +public class User implements Observer { + private String name; + private String message; + + public User(String name) { + this.name = name; + } + + @Override + public void update(String message) { + this.message = message; + read(); + } + + public void read() { + System.out.println(name + " 收到推送消息: " + message); + } +} diff --git a/src/com/blankj/custom/desingn_pattern/observerable/WechatServer.java b/src/com/blankj/custom/desingn_pattern/observerable/WechatServer.java new file mode 100644 index 00000000..527d6ffa --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/observerable/WechatServer.java @@ -0,0 +1,49 @@ +package com.blankj.custom.desingn_pattern.observerable; + +import java.util.ArrayList; +import java.util.List; + +/** + * 被观察者,也就是微信公众号服务 + * 实现了Observerable接口,对Observerable接口的三个方法进行了具体实现 + * + * @author jstao + */ +public class WechatServer implements Observerable { + + //注意到这个List集合的泛型参数为Observer接口,设计原则:面向接口编程而不是面向实现编程 + private List list; + private String message; + + public WechatServer() { + list = new ArrayList(); + } + + @Override + public void registerObserver(Observer o) { + list.add(o); + } + + @Override + public void removeObserver(Observer o) { + if (!list.isEmpty()) + list.remove(o); + } + + //遍历 + @Override + public void notifyObserver() { + for (int i = 0; i < list.size(); i++) { + Observer oserver = list.get(i); + oserver.update(message); + } + } + + public void setInfomation(String s) { + this.message = s; + System.out.println("微信服务更新消息: " + s); + //消息更新,通知所有观察者 + notifyObserver(); + } + +} diff --git a/src/com/blankj/custom/desingn_pattern/polymorphic/Child.java b/src/com/blankj/custom/desingn_pattern/polymorphic/Child.java new file mode 100644 index 00000000..27716f89 --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/polymorphic/Child.java @@ -0,0 +1,18 @@ +package com.blankj.custom.desingn_pattern.polymorphic; + +public class Child extends Parent { + String name = "C"; + String sex = "F"; + + public Child() { + System.out.println("Child init"); + System.out.println("Child" + this.name); + System.out.println("Child" + this.sex); + System.out.println("Child" + super.name); + System.out.println("Child" + super.sex); + } + + public void say(){ + System.out.println("Child say"); + } +} diff --git a/src/com/blankj/custom/desingn_pattern/polymorphic/Parent.java b/src/com/blankj/custom/desingn_pattern/polymorphic/Parent.java new file mode 100644 index 00000000..0a466362 --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/polymorphic/Parent.java @@ -0,0 +1,16 @@ +package com.blankj.custom.desingn_pattern.polymorphic; + +public class Parent { + String name = "P"; + String sex = "M"; + + public void say(){ + System.out.println("Parent say"); + } + + public Parent() { + System.out.println("Parent init"); + System.out.println("Parent" + this.name); + System.out.println("Parent" + this.sex); + } +} diff --git a/src/com/blankj/custom/desingn_pattern/polymorphic/Test.java b/src/com/blankj/custom/desingn_pattern/polymorphic/Test.java new file mode 100644 index 00000000..013dd792 --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/polymorphic/Test.java @@ -0,0 +1,22 @@ +package com.blankj.custom.desingn_pattern.polymorphic; + +public class Test { + // +// 初始化过程: +// 1. 初始化父类中的静态成员变量和静态代码块 ; +// 2. 初始化子类中的静态成员变量和静态代码块 ; +// 3.初始化父类的普通成员变量和代码块,再执行父类的构造方法; +// 4.初始化子类的普通成员变量和代码块,再执行子类的构造方法; +// +// (1)初始化父类的普通成员变量和代码块,执行 Y y=new Y(); 输出Y +//(2)再执行父类的构造方法;输出X +//(3) 初始化子类的普通成员变量和代码块,执行 Y y=new Y(); 输出Y +//(4)再执行子类的构造方法;输出Z +// + public static void main(String[] args) { + Child child = new Child(); + child.say(); + Parent child1 = new Child(); + child1.say(); + } +} diff --git a/src/com/blankj/custom/desingn_pattern/producer/Consumer.java b/src/com/blankj/custom/desingn_pattern/producer/Consumer.java new file mode 100644 index 00000000..988a63fb --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/producer/Consumer.java @@ -0,0 +1,27 @@ +package com.blankj.custom.desingn_pattern.producer; + +import java.util.concurrent.BlockingQueue; + +public class Consumer implements Runnable { + private BlockingQueue queue; + private String consumer; + + public Consumer(BlockingQueue queue, String consumer) { + this.queue = queue; + if (null != consumer) + this.consumer = consumer; + else + this.consumer = "null "; + } + + @Override + public void run() { + try { + String uuid = queue.take(); + System.out.println(consumer + " decayed " + uuid + + " " + Thread.currentThread()); + } catch (InterruptedException e) { + System.out.println(e.getMessage()); + } + } +} diff --git a/src/com/blankj/custom/desingn_pattern/producer/Producer.java b/src/com/blankj/custom/desingn_pattern/producer/Producer.java new file mode 100644 index 00000000..e424b027 --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/producer/Producer.java @@ -0,0 +1,29 @@ +package com.blankj.custom.desingn_pattern.producer; + +import java.util.UUID; +import java.util.concurrent.BlockingQueue; + +public class Producer implements Runnable { + private BlockingQueue queue; + private String produce; + + public Producer(BlockingQueue queue, String produce) { + this.queue = queue; + if (null != produce) + this.produce = produce; + else this.produce = "null "; + } + + @Override + public void run() { + String uuid = UUID.randomUUID().toString(); + try { + Thread.sleep(200);//生产需要时间 + queue.put(produce + " : " + uuid); + System.out.println("Produce \"" + produce + "\" : " + uuid + " " + Thread.currentThread()); + + } catch (InterruptedException e) { + System.out.println(e.getMessage()); + } + } +} diff --git a/src/com/blankj/custom/desingn_pattern/producer/Tester.java b/src/com/blankj/custom/desingn_pattern/producer/Tester.java new file mode 100644 index 00000000..1bbe2421 --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/producer/Tester.java @@ -0,0 +1,22 @@ +package com.blankj.custom.desingn_pattern.producer; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; + +public class Tester { + public static void main(String[] args) { + // 队列 + LinkedBlockingQueue queue = new LinkedBlockingQueue(10); + ExecutorService service = Executors.newCachedThreadPool(); + for (int i = 0; i < 6; i++) { + service.submit(new Consumer(queue, "X二代" + i)); + service.submit(new Consumer(queue, "导演" + i)); + } + for (int i = 0; i < 6; i++) { + service.submit(new Producer(queue, "黄金酒," + i)); + service.submit(new Producer(queue, "美女演员" + i)); + } + service.shutdown(); + } +} diff --git a/src/com/blankj/custom/desingn_pattern/proxys/dynamicProxy/Client.java b/src/com/blankj/custom/desingn_pattern/proxys/dynamicProxy/Client.java new file mode 100644 index 00000000..c0933ec1 --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/proxys/dynamicProxy/Client.java @@ -0,0 +1,23 @@ +package com.blankj.custom.desingn_pattern.proxys.dynamicProxy; + +import java.lang.reflect.InvocationHandler; + +public class Client { + public static void main(String[] args) { + +// 一个典型的动态代理创建对象过程可分为以下四个步骤: +// 1、通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(...); +// 2、通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类 +// Class clazz = Proxy.getProxyClass(classLoader,new Class[]{...}); +// 3、通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型 +// Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class}); +// 4、通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入 +// Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler)); + + ISubject subject = new RealSubject(); + + InvocationHandler handler = new MyInvocationHandler(subject); + ISubject proxy = DynamicProxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(), handler); + proxy.request(); + } +} diff --git a/src/com/blankj/custom/desingn_pattern/proxys/dynamicProxy/DynamicProxy.java b/src/com/blankj/custom/desingn_pattern/proxys/dynamicProxy/DynamicProxy.java new file mode 100644 index 00000000..10308b10 --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/proxys/dynamicProxy/DynamicProxy.java @@ -0,0 +1,11 @@ +package com.blankj.custom.desingn_pattern.proxys.dynamicProxy; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Proxy; + +public class DynamicProxy { + @SuppressWarnings("unchecked") + public static T newProxyInstance(ClassLoader classLoader, Class[] interfaces, InvocationHandler handler) { + return (T) Proxy.newProxyInstance(classLoader, interfaces, handler); + } +} diff --git a/src/com/blankj/custom/desingn_pattern/proxys/dynamicProxy/ISubject.java b/src/com/blankj/custom/desingn_pattern/proxys/dynamicProxy/ISubject.java new file mode 100644 index 00000000..0e5f2cc5 --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/proxys/dynamicProxy/ISubject.java @@ -0,0 +1,6 @@ +package com.blankj.custom.desingn_pattern.proxys.dynamicProxy; + +//https://www.jianshu.com/p/78fdd12c2c71 +public interface ISubject { + void request(); +} diff --git a/src/com/blankj/custom/desingn_pattern/proxys/dynamicProxy/MyInvocationHandler.java b/src/com/blankj/custom/desingn_pattern/proxys/dynamicProxy/MyInvocationHandler.java new file mode 100644 index 00000000..913e12d1 --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/proxys/dynamicProxy/MyInvocationHandler.java @@ -0,0 +1,17 @@ +package com.blankj.custom.desingn_pattern.proxys.dynamicProxy; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; + +public class MyInvocationHandler implements InvocationHandler { + private Object target = null; + + public MyInvocationHandler(Object object) { + this.target = object; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + return method.invoke(this.target, args); + } +} diff --git a/src/com/blankj/custom/desingn_pattern/proxys/dynamicProxy/RealSubject.java b/src/com/blankj/custom/desingn_pattern/proxys/dynamicProxy/RealSubject.java new file mode 100644 index 00000000..1e46b233 --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/proxys/dynamicProxy/RealSubject.java @@ -0,0 +1,8 @@ +package com.blankj.custom.desingn_pattern.proxys.dynamicProxy; + +public class RealSubject implements ISubject { + @Override + public void request() { + System.out.println("我是真实对象"); + } +} diff --git a/src/com/blankj/custom/desingn_pattern/proxys/staticProxy/Client.java b/src/com/blankj/custom/desingn_pattern/proxys/staticProxy/Client.java new file mode 100644 index 00000000..f4f17c7b --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/proxys/staticProxy/Client.java @@ -0,0 +1,10 @@ +package com.blankj.custom.desingn_pattern.proxys.staticProxy; + +public class Client { + public static void main(String[] args) { + ISubject subject = new RealSubject(); + //让RealSubject这个借口的实现类来完成任务 + Proxy proxy = new Proxy(subject); + proxy.request(); + } +} diff --git a/src/com/blankj/custom/desingn_pattern/proxys/staticProxy/ISubject.java b/src/com/blankj/custom/desingn_pattern/proxys/staticProxy/ISubject.java new file mode 100644 index 00000000..7530a661 --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/proxys/staticProxy/ISubject.java @@ -0,0 +1,6 @@ +package com.blankj.custom.desingn_pattern.proxys.staticProxy; + +//https://www.jianshu.com/p/78fdd12c2c71 +public interface ISubject { + void request(); +} diff --git a/src/com/blankj/custom/desingn_pattern/proxys/staticProxy/Proxy.java b/src/com/blankj/custom/desingn_pattern/proxys/staticProxy/Proxy.java new file mode 100644 index 00000000..8eba6c99 --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/proxys/staticProxy/Proxy.java @@ -0,0 +1,15 @@ +package com.blankj.custom.desingn_pattern.proxys.staticProxy; + +public class Proxy implements ISubject { + private ISubject subject; + + //传入接口的实现类 + public Proxy(ISubject subject) { + this.subject = subject; + } + + @Override + public void request() { + this.subject.request(); + } +} diff --git a/src/com/blankj/custom/desingn_pattern/proxys/staticProxy/RealSubject.java b/src/com/blankj/custom/desingn_pattern/proxys/staticProxy/RealSubject.java new file mode 100644 index 00000000..4e26abb7 --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/proxys/staticProxy/RealSubject.java @@ -0,0 +1,8 @@ +package com.blankj.custom.desingn_pattern.proxys.staticProxy; + +public class RealSubject implements ISubject{ + @Override + public void request() { + System.out.println("我是真实对象"); + } +} diff --git a/src/com/blankj/custom/desingn_pattern/single/Single1.java b/src/com/blankj/custom/desingn_pattern/single/Single1.java new file mode 100755 index 00000000..8581087f --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/single/Single1.java @@ -0,0 +1,23 @@ +package com.blankj.custom.desingn_pattern.single; + +// 懒汉式(线程安全问题) +public class Single1 { + private static Single1 instance; + + private Single1() { + System.out.println("构造函数运行-----"); + } + + public static Single1 getInstance() { + if (instance == null) { + instance = new Single1(); + } + return instance; + } + + public static void main(String[] args) { + Single1 instance = Single1.getInstance(); + Single1 instance2 = Single1.getInstance(); + System.out.println(instance == instance2); + } +} diff --git a/src/com/blankj/custom/desingn_pattern/single/Single2.java b/src/com/blankj/custom/desingn_pattern/single/Single2.java new file mode 100755 index 00000000..45c7025b --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/single/Single2.java @@ -0,0 +1,23 @@ +package com.blankj.custom.desingn_pattern.single; + +// 懒汉式() +public class Single2 { + private static Single2 instance; + + private Single2() { + System.out.println("Single2构造函数运行-----"); + } + + public static synchronized Single2 getInstance() { + if (instance == null) { + instance = new Single2(); + } + return instance; + } + + public static void main(String[] args) { + Single2 instance = Single2.getInstance(); + Single2 instance2 = Single2.getInstance(); + System.out.println("222:" + (instance == instance2)); + } +} diff --git a/src/com/blankj/custom/desingn_pattern/single/Single3.java b/src/com/blankj/custom/desingn_pattern/single/Single3.java new file mode 100755 index 00000000..f22abb2f --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/single/Single3.java @@ -0,0 +1,25 @@ +package com.blankj.custom.desingn_pattern.single; + +/** + * 码家学院 + * + * @author Liao 单例模式,饿汉式 + */ +public class Single3 { + + private static Single3 instance = new Single3(); + + private Single3() { + System.out.println("构造函数--"); + } + + public static Single3 getInstance() { + return instance; + } + + public static void main(String[] args) { + Single3 instance1 = Single3.getInstance(); + Single3 instance2 = Single3.getInstance(); + System.out.println("333:" + (instance1 == instance2)); + } +} diff --git a/src/com/blankj/custom/desingn_pattern/strategy/ConcreteStrategyA.java b/src/com/blankj/custom/desingn_pattern/strategy/ConcreteStrategyA.java new file mode 100644 index 00000000..611f29a6 --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/strategy/ConcreteStrategyA.java @@ -0,0 +1,8 @@ +package com.blankj.custom.desingn_pattern.strategy; + +public class ConcreteStrategyA implements Strategy { + @Override + public void strategyInterface() { + //相关的业务 + } +} diff --git a/src/com/blankj/custom/desingn_pattern/strategy/ConcreteStrategyB.java b/src/com/blankj/custom/desingn_pattern/strategy/ConcreteStrategyB.java new file mode 100644 index 00000000..f65aaeff --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/strategy/ConcreteStrategyB.java @@ -0,0 +1,8 @@ +package com.blankj.custom.desingn_pattern.strategy; + +public class ConcreteStrategyB implements Strategy { + @Override + public void strategyInterface() { + //相关的业务 + } +} diff --git a/src/com/blankj/custom/desingn_pattern/strategy/Context.java b/src/com/blankj/custom/desingn_pattern/strategy/Context.java new file mode 100644 index 00000000..5520d265 --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/strategy/Context.java @@ -0,0 +1,22 @@ +package com.blankj.custom.desingn_pattern.strategy; + +public class Context { + //持有一个具体策略的对象 + private Strategy strategy; + + /** + * 构造函数,传入一个具体策略对象 + * + * @param strategy 具体策略对象 + */ + public Context(Strategy strategy) { + this.strategy = strategy; + } + + /** + * 策略方法 + */ + public void contextInterface() { + strategy.strategyInterface(); + } +} diff --git a/src/com/blankj/custom/desingn_pattern/strategy/ReadMe b/src/com/blankj/custom/desingn_pattern/strategy/ReadMe new file mode 100644 index 00000000..fdbe2745 --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/strategy/ReadMe @@ -0,0 +1,7 @@ +这个模式涉及到三个角色: + +环境(Context)角色:持有一个Strategy的引用。 + +抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。 + +具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。 \ No newline at end of file diff --git a/src/com/blankj/custom/desingn_pattern/strategy/Strategy.java b/src/com/blankj/custom/desingn_pattern/strategy/Strategy.java new file mode 100644 index 00000000..40a18d8a --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/strategy/Strategy.java @@ -0,0 +1,8 @@ +package com.blankj.custom.desingn_pattern.strategy; + +public interface Strategy { + /** + * 策略方法 + */ + void strategyInterface(); +} diff --git a/src/com/blankj/custom/desingn_pattern/strategy/example/CalPrice.java b/src/com/blankj/custom/desingn_pattern/strategy/example/CalPrice.java new file mode 100644 index 00000000..d5d795f2 --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/strategy/example/CalPrice.java @@ -0,0 +1,6 @@ +package com.blankj.custom.desingn_pattern.strategy.example; + +public interface CalPrice { + //根据原价返回一个最终的价格 + Double calPrice(Double orgnicPrice); +} diff --git a/src/com/blankj/custom/desingn_pattern/strategy/example/CalPriceFactory.java b/src/com/blankj/custom/desingn_pattern/strategy/example/CalPriceFactory.java new file mode 100644 index 00000000..34469fd6 --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/strategy/example/CalPriceFactory.java @@ -0,0 +1,111 @@ +package com.blankj.custom.desingn_pattern.strategy.example; + +public class CalPriceFactory { + private CalPriceFactory() { + } + + //根据客户的总金额产生相应的策略 + public static CalPrice createCalPrice(Player customer) { + if (customer.getTotalAmount() > 30000) {//3000则改为金牌会员计算方式 + return new GoldVip(); + } else if (customer.getTotalAmount() > 20000) {//类似 + return new SuperVip(); + } else if (customer.getTotalAmount() > 10000) {//类似 + return new Vip(); + } else { + return new Orgnic(); + } + } + +// private static final String CAL_PRICE_PACKAGE = "com.blankj.custom.desingn_pattern.strategy.example";//这里是一个常量,表示我们扫描策略的包 +// +// private ClassLoader classLoader = getClass().getClassLoader(); +// +// private List> calPriceList;//策略列表 +// +// //根据玩家的总金额产生相应的策略 +// public CalPrice createCalPrice(Player player) { +// //在策略列表查找策略 +// for (Class clazz : calPriceList) { +// PriceRegion validRegion = handleAnnotation(clazz);//获取该策略的注解 +// //判断金额是否在注解的区间 +// if (player.getTotalAmount() > validRegion.min() && player.getTotalAmount() < validRegion.max()) { +// try { +// //是的话我们返回一个当前策略的实例 +// return clazz.newInstance(); +// } catch (Exception e) { +// throw new RuntimeException("策略获得失败"); +// } +// } +// } +// throw new RuntimeException("策略获得失败"); +// } +// +// private PriceRegion handleAnnotation(Class clazz) { +// Annotation[] annotations = clazz.getDeclaredAnnotations(); +// if (annotations == null || annotations.length == 0) { +// return null; +// } +// for (int i = 0; i < annotations.length; i++) { +// if (annotations[i] instanceof PriceRegion) { +// return (PriceRegion) annotations[i]; +// } +// } +// return null; +// } +// +// //单例 +// private CalPriceFactory() { +// init(); +// } +// +// //在工厂初始化时要初始化策略列表 +// private void init() { +// calPriceList = new ArrayList>(); +// File[] resources = getResources();//获取到包下所有的class文件 +// Class calPriceClazz = null; +// try { +// calPriceClazz = (Class) classLoader.loadClass(CalPrice.class.getName());//使用相同的加载器加载策略接口 +// } catch (ClassNotFoundException e1) { +// throw new RuntimeException("未找到策略接口"); +// } +// for (int i = 0; i < resources.length; i++) { +// try { +// //载入包下的类 +// Class clazz = classLoader.loadClass(CAL_PRICE_PACKAGE + "." + resources[i].getName().replace(".class", "")); +// //判断是否是CalPrice的实现类并且不是CalPrice它本身,满足的话加入到策略列表 +// if (CalPrice.class.isAssignableFrom(clazz) && clazz != calPriceClazz) { +// calPriceList.add((Class) clazz); +// } +// } catch (ClassNotFoundException e) { +// e.printStackTrace(); +// } +// } +// } +// +// //获取扫描的包下面所有的class文件 +// private File[] getResources() { +// try { +// File file = new File(classLoader.getResource(CAL_PRICE_PACKAGE.replace(".", "/")).toURI()); +// return file.listFiles(new FileFilter() { +// public boolean accept(File pathname) { +// if (pathname.getName().endsWith(".class")) {//我们只扫描class文件 +// return true; +// } +// return false; +// } +// }); +// } catch (URISyntaxException e) { +// throw new RuntimeException("未找到策略资源"); +// } +// } +// +// public static CalPriceFactory getInstance() { +// return CalPriceFactoryInstance.instance; +// } +// +// private static class CalPriceFactoryInstance { +// +// private static CalPriceFactory instance = new CalPriceFactory(); +// } +} diff --git a/src/com/blankj/custom/desingn_pattern/strategy/example/Client.java b/src/com/blankj/custom/desingn_pattern/strategy/example/Client.java new file mode 100644 index 00000000..e473471f --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/strategy/example/Client.java @@ -0,0 +1,30 @@ +package com.blankj.custom.desingn_pattern.strategy.example; + + +//https://blog.csdn.net/u012124438/article/details/70039943/ +// +//策略模式的定义和使用场景 +// +// 定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们可以相互替换,让算法独立于使用它的客户而独立变化。 +// +// 分析下定义,策略模式定义和封装了一系列的算法,它们是可以相互替换的,也就是说它们具有共性,而它们的共性就体现在策略接口的行为上,另外为了达到最后一句话的目的,也就是说让算法独立于使用它的客户而独立变化,我们需要让客户端依赖于策略接口。 +// +// 策略模式的使用场景: +// +// 1.针对同一类型问题的多种处理方式,仅仅是具体行为有差别时; +// 2.需要安全地封装多种同一类型的操作时; +// 3.出现同一抽象类有多个子类,而又需要使用 if-else 或者 switch-case 来选择具体子类时。 + +public class Client { + public static void main(String[] args) { + Player player = new Player(); + player.buy(5000D); + System.out.println("玩家需要付钱:" + player.calLastAmount()); + player.buy(12000D); + System.out.println("玩家需要付钱:" + player.calLastAmount()); + player.buy(12000D); + System.out.println("玩家需要付钱:" + player.calLastAmount()); + player.buy(12000D); + System.out.println("玩家需要付钱:" + player.calLastAmount()); + } +} diff --git a/src/com/blankj/custom/desingn_pattern/strategy/example/GoldVip.java b/src/com/blankj/custom/desingn_pattern/strategy/example/GoldVip.java new file mode 100644 index 00000000..4d3f70cb --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/strategy/example/GoldVip.java @@ -0,0 +1,9 @@ +package com.blankj.custom.desingn_pattern.strategy.example; + +@PriceRegion(min=3000) +public class GoldVip implements CalPrice { + @Override + public Double calPrice(Double orgnicPrice) { + return orgnicPrice * 0.7; + } +} diff --git a/src/com/blankj/custom/desingn_pattern/strategy/example/Orgnic.java b/src/com/blankj/custom/desingn_pattern/strategy/example/Orgnic.java new file mode 100644 index 00000000..662efebe --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/strategy/example/Orgnic.java @@ -0,0 +1,9 @@ +package com.blankj.custom.desingn_pattern.strategy.example; + +@PriceRegion(max = 10000) +public class Orgnic implements CalPrice { + @Override + public Double calPrice(Double orgnicPrice) { + return orgnicPrice; + } +} diff --git a/src/com/blankj/custom/desingn_pattern/strategy/example/Player.java b/src/com/blankj/custom/desingn_pattern/strategy/example/Player.java new file mode 100644 index 00000000..ab193bfa --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/strategy/example/Player.java @@ -0,0 +1,38 @@ +package com.blankj.custom.desingn_pattern.strategy.example; + +public class Player { + private Double totalAmount = 0D;//客户在鹅厂消费的总额 + private Double amount = 0D;//客户单次消费金额 + private CalPrice calPrice = new Orgnic();//每个客户都有一个计算价格的策略,初始都是普通计算,即原价 + +// //客户购买皮肤,就会增加它的总额 +// public void buy(Double amount) { +// this.amount = amount; +// totalAmount += amount; +// if (totalAmount > 30000) {//30000则改为金牌会员计算方式 +// calPrice = new GoldVip(); +// } else if (totalAmount > 20000) {//类似 +// calPrice = new SuperVip(); +// } else if (totalAmount > 10000) {//类似 +// calPrice = new Vip(); +// } +// } + + //客户购买皮肤,就会增加它的总额 + public void buy(Double amount) { + this.amount = amount; + totalAmount += amount; + /* 变化点,我们将策略的制定转移给了策略工厂,将这部分责任分离出去 */ + calPrice = CalPriceFactory.createCalPrice(this); +// calPrice = CalPriceFactory.getInstance().createCalPrice(this); + } + + //计算客户最终要付的钱 + public Double calLastAmount() { + return calPrice.calPrice(amount); + } + + public Double getTotalAmount() { + return totalAmount; + } +} diff --git a/src/com/blankj/custom/desingn_pattern/strategy/example/PriceRegion.java b/src/com/blankj/custom/desingn_pattern/strategy/example/PriceRegion.java new file mode 100644 index 00000000..9f509315 --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/strategy/example/PriceRegion.java @@ -0,0 +1,14 @@ +package com.blankj.custom.desingn_pattern.strategy.example; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +//这是有效价格区间注解,可以给策略添加有效区间的设置 +@Target(ElementType.TYPE)//表示只能给类添加该注解 +@Retention(RetentionPolicy.RUNTIME)//这个必须要将注解保留在运行时 +public @interface PriceRegion { + int max() default Integer.MAX_VALUE; + int min() default Integer.MIN_VALUE; +} diff --git a/src/com/blankj/custom/desingn_pattern/strategy/example/SuperVip.java b/src/com/blankj/custom/desingn_pattern/strategy/example/SuperVip.java new file mode 100644 index 00000000..9a70ba6c --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/strategy/example/SuperVip.java @@ -0,0 +1,9 @@ +package com.blankj.custom.desingn_pattern.strategy.example; + +@PriceRegion(min=20000,max=30000) +public class SuperVip implements CalPrice { + @Override + public Double calPrice(Double orgnicPrice) { + return orgnicPrice * 0.8; + } +} diff --git a/src/com/blankj/custom/desingn_pattern/strategy/example/Vip.java b/src/com/blankj/custom/desingn_pattern/strategy/example/Vip.java new file mode 100644 index 00000000..4b92c991 --- /dev/null +++ b/src/com/blankj/custom/desingn_pattern/strategy/example/Vip.java @@ -0,0 +1,9 @@ +package com.blankj.custom.desingn_pattern.strategy.example; + +@PriceRegion(max=20000) +public class Vip implements CalPrice { + @Override + public Double calPrice(Double orgnicPrice) { + return orgnicPrice * 0.9; + } +} diff --git a/src/com/blankj/custom/piped/PipedStreamTest.java b/src/com/blankj/custom/piped/PipedStreamTest.java new file mode 100644 index 00000000..465a3b9c --- /dev/null +++ b/src/com/blankj/custom/piped/PipedStreamTest.java @@ -0,0 +1,42 @@ +package com.blankj.custom.piped; + +import java.io.IOException; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; + +@SuppressWarnings("all") +/** + * 管道输入流和管道输出流的交互程序 + */ + +//http://www.bijishequ.com/detail/530061 + +public class PipedStreamTest { + + public static void main(String[] args) { + Sender t1 = new Sender(); + + Receiver t2 = new Receiver(); + + PipedOutputStream out = t1.getOutputStream(); + + PipedInputStream in = t2.getInputStream(); + + try { + //管道连接。下面2句话的本质是一样。 + //out.connect(in); + in.connect(out); + + /** + * Thread类的START方法: + * 使该线程开始执行;Java 虚拟机调用该线程的 run 方法。 + * 结果是两个线程并发地运行;当前线程(从调用返回给 start 方法)和另一个线程(执行其 run 方法)。 + * 多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动。 + */ + t1.start(); + t2.start(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/com/blankj/custom/piped/Receiver.java b/src/com/blankj/custom/piped/Receiver.java new file mode 100644 index 00000000..9ffd8fb1 --- /dev/null +++ b/src/com/blankj/custom/piped/Receiver.java @@ -0,0 +1,65 @@ +package com.blankj.custom.piped; + +import java.io.IOException; +import java.io.PipedInputStream; + +@SuppressWarnings("all") +/** + * 接收者线程 + */ +public class Receiver extends Thread { + + // 管道输入流对象。 + // 它和“管道输出流(PipedOutputStream)”对象绑定, + // 从而可以接收“管道输出流”的数据,再让用户读取。 + private PipedInputStream in = new PipedInputStream(); + + // 获得“管道输入流”对象 + public PipedInputStream getInputStream() { + return in; + } + + @Override + public void run() { + readMessageOnce(); + //readMessageContinued() ; + } + + // 从“管道输入流”中读取1次数据 + public void readMessageOnce() { + // 虽然buf的大小是2048个字节,但最多只会从“管道输入流”中读取1024个字节。 + // 因为,“管道输入流”的缓冲区大小默认只有1024个字节。 + byte[] buf = new byte[2048]; + try { + int len = in.read(buf); + System.out.println(new String(buf, 0, len)); + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + // 从“管道输入流”读取>1024个字节时,就停止读取 + public void readMessageContinued() { + int total = 0; + while (true) { + byte[] buf = new byte[1024]; + try { + int len = in.read(buf); + total += len; + System.out.println(new String(buf, 0, len)); + // 若读取的字节总数>1024,则退出循环。 + if (total > 1024) + break; + } catch (IOException e) { + e.printStackTrace(); + } + } + + try { + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/com/blankj/custom/piped/Sender.java b/src/com/blankj/custom/piped/Sender.java new file mode 100644 index 00000000..e3d182fc --- /dev/null +++ b/src/com/blankj/custom/piped/Sender.java @@ -0,0 +1,57 @@ +package com.blankj.custom.piped; + +import java.io.IOException; +import java.io.PipedOutputStream; + +@SuppressWarnings("all") +/** + * 发送者线程 + */ +public class Sender extends Thread { + + // 管道输出流对象。 + // 它和“管道输入流(PipedInputStream)”对象绑定, + // 从而可以将数据发送给“管道输入流”的数据,然后用户可以从“管道输入流”读取数据。 + private PipedOutputStream out = new PipedOutputStream(); + + // 获得“管道输出流”对象 + public PipedOutputStream getOutputStream() { + return out; + } + + @Override + public void run() { + writeShortMessage(); + //writeLongMessage(); + } + + // 向“管道输出流”中写入一则较简短的消息:"this is a short message" + private void writeShortMessage() { + String strInfo = "this is a short message"; + try { + out.write(strInfo.getBytes()); + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + // 向“管道输出流”中写入一则较长的消息 + private void writeLongMessage() { + StringBuilder sb = new StringBuilder(); + // 通过for循环写入1020个字节 + for (int i = 0; i < 102; i++) + sb.append("0123456789"); + // 再写入26个字节。 + sb.append("abcdefghijklmnopqrstuvwxyz"); + // str的总长度是1020+26=1046个字节 + String str = sb.toString(); + try { + // 将1046个字节写入到“管道输出流”中 + out.write(str.getBytes()); + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/com/blankj/custom/pretest/DiceSum.java b/src/com/blankj/custom/pretest/DiceSum.java new file mode 100644 index 00000000..b521e7eb --- /dev/null +++ b/src/com/blankj/custom/pretest/DiceSum.java @@ -0,0 +1,45 @@ +package com.blankj.custom.pretest; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +public class DiceSum { + + public static void main(String[] args) { + int[] candidates = {1, 2, 3, 4, 5, 6}; + int target = 610; + System.out.println(combination(candidates, target).size()); + } + + public static List> combination(int[] candidates, int target) { + List> res = new LinkedList>(); + List tmp = new LinkedList(); + // 先将数组排序避免重复搜素 + Arrays.sort(candidates); + helper(res, candidates, target, 0, tmp); + return res; + } + + private static void helper(List> res, int[] candidates, int target, int index, List tmp) { + // 如果当前和已经大于目标,说明该路径错误 + if (target < 0) { + return; + // 如果当前和等于目标,说明这是一条正确路径,记录该路径 + } else if (target == 0) { + List oneComb = new LinkedList(tmp); + res.add(oneComb); + // 否则,对剩余所有可能性进行深度优先搜索 + } else { + // 选取之后的每个数字都是一种可能性 + for (int i = index; i < candidates.length; i++) { + // 典型的先加入元素,再进行搜索,递归回来再移出元素的DFS解法 + if (i > 0 && candidates[i] == candidates[i - 1]) + continue; + tmp.add(candidates[i]); + helper(res, candidates, target - candidates[i], i, tmp); + tmp.remove(tmp.size() - 1); + } + } + } +} diff --git a/src/com/blankj/custom/pretest/Fibonacci.java b/src/com/blankj/custom/pretest/Fibonacci.java new file mode 100644 index 00000000..ead7b38f --- /dev/null +++ b/src/com/blankj/custom/pretest/Fibonacci.java @@ -0,0 +1,104 @@ +package com.blankj.custom.pretest; + +import java.math.BigInteger; +//1、1、2、3、5、8、13、21 + +public class Fibonacci { + // 1. 递归 复杂度为O(2^n),即2的n次方 + static BigInteger fib1(int n) { + if (n == 1 || n == 2) { + return BigInteger.valueOf(1); + } else { + return fib1(n - 1).add(fib1(n - 2)); + } + } + + // 2. 循环 O(n) + static BigInteger fib2(int n) { + BigInteger a = BigInteger.valueOf(0); + BigInteger b = BigInteger.valueOf(1); + for (int j = 2; j <= n; j++) { + BigInteger tmp = a;//将第一个值p赋给tmp + a = b; //将第二个值q赋给p,以后每一次赋值都将得到的最新的F(n)赋给p,从后面语句可//以看出,q储存的为最新的F(n) + b = tmp.add(b); + } + return b; + } + + // 3. matrix log(n) + /** + * 求斐波那契数列
+ *
+     * [F(n+1) F(n)]    [1  1 ]^n   (n次方,可以使用归纳法证明)
+ * | | =| |
+ * [F(n) F(n-1)] [1 0 ]
+ *
+ * + * @author bing + */ + +// https://blog.csdn.net/flyfish1986/article/details/48014523 + + // 关联矩阵 + private static final BigInteger[][] UNIT = {{BigInteger.valueOf(1), BigInteger.valueOf(1)}, {BigInteger.valueOf(1), BigInteger.valueOf(0)}}; + // 全0矩阵 + private static final BigInteger[][] ZERO = {{BigInteger.valueOf(0), BigInteger.valueOf(0)}, {BigInteger.valueOf(0), BigInteger.valueOf(0)}}; + + /** + * 求斐波那契数列 + * + * @param n + * @return + */ +// 问题转换为二阶矩阵的n次幂 + public static BigInteger[][] fib3(int n) { + if (n == 0) { + return ZERO; + } + if (n == 1) { + return UNIT; + } + // n是偶数 + //以计算A6为例 + //将6转化成二进制110 为A的4次方 和 A的2次方 + if ((n & 1) == 0) { + BigInteger[][] matrix = fib3(n >> 1); + return matrixMultiply(matrix, matrix); + } + // n是奇数 + //10进制7 = 二进制 111 +// 例如A7=A4次方∗A2次方∗A + BigInteger[][] matrix = fib3((n - 1) >> 1); + return matrixMultiply(matrixMultiply(matrix, matrix), UNIT); + } + + /** + * 矩阵相乘 + * + * @param m r1*c1 + * @param n c1*c2 + * @return 新矩阵, r1*c2 + */ + public static BigInteger[][] matrixMultiply(BigInteger[][] m, BigInteger[][] n) { + int rows = m.length; + int cols = n[0].length; + BigInteger[][] r = new BigInteger[rows][cols]; + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + r[i][j] = BigInteger.valueOf(0); + for (int k = 0; k < m[i].length; k++) { + r[i][j] = r[i][j].add(m[i][k].multiply(n[k][j])); + } + } + } + return r; + } + + public static void main(String[] args) { + int n = 81; +// System.out.println("Fibonacci of " + n + +// "th term" + " " + "is" + " " + fib2(n)); + BigInteger[][] m = fib3(n); + System.out.println(m[0][1]); + } +} diff --git a/src/com/blankj/custom/pretest/PrintTree.java b/src/com/blankj/custom/pretest/PrintTree.java new file mode 100644 index 00000000..839d9702 --- /dev/null +++ b/src/com/blankj/custom/pretest/PrintTree.java @@ -0,0 +1,56 @@ +package com.blankj.custom.pretest; + +import com.blankj.custom.structure.TreeNode; + +import java.util.LinkedList; +import java.util.Queue; + +public class PrintTree { + public static void main(String[] args) { + TreeNode node0 = new TreeNode(0, null, null); + TreeNode node7 = new TreeNode(7, null, null); + TreeNode node9 = new TreeNode(9, null, null); + TreeNode node1R = new TreeNode(1, null, null); + TreeNode node1L = new TreeNode(1, node0, node7); + TreeNode node3 = new TreeNode(3, node9, node1R); + TreeNode node2 = new TreeNode(2, node1L, node3); + printTree(node2); + } + + public static void printTree(TreeNode root) { + if (root == null) + return; + Queue queue = new LinkedList<>(); + +// 需要额外两个变量。一个变量用来保存当前层 还未打印的结点个数,另一个变量保存下一层待打印的结点个数 + int current;//当前层 还未打印的结点个数 + int next;//下一层结点个数 + StringBuilder nodeVal = new StringBuilder(); + + queue.offer(root); + current = 1; + next = 0; + while (!queue.isEmpty()) { + TreeNode currentNode = queue.poll(); + nodeVal.append("(").append(currentNode.val).append(")").append(","); + current--; + + if (currentNode.left != null) { + //queue加入节点 + queue.offer(currentNode.left); + next++; + } + if (currentNode.right != null) { + //queue加入节点 + queue.offer(currentNode.right); + next++; + } + if (current == 0) { + current = next; + next = 0; + System.out.println(nodeVal.toString().substring(0, nodeVal.lastIndexOf(","))); + nodeVal = new StringBuilder(); + } + } + } +} diff --git a/src/com/blankj/custom/rxjava/Observable.java b/src/com/blankj/custom/rxjava/Observable.java new file mode 100644 index 00000000..921d09b1 --- /dev/null +++ b/src/com/blankj/custom/rxjava/Observable.java @@ -0,0 +1,30 @@ +package com.blankj.custom.rxjava; + +public class Observable { + //接口,每个Observable里面有一个OnSubscribe对象,只有一个方法(void call(Subscriber subscriber);), + // 用来产生数据流,这是典型的命令模式。 + public interface OnSubscribe { +// void call(Subscriber subscriber); + void call(Subscriber subscriber); + } + + //接口实现类 + final OnSubscribe onSubscribe; + + //构造函数 + private Observable(OnSubscribe onSubscribe) { + this.onSubscribe = onSubscribe; + } + + // 告诉编译器我这个地方有个类型 静态方法必须加 + public static Observable create(OnSubscribe onSubscribe) { + return new Observable(onSubscribe); + } + + public void subscribe(Subscriber subscriber) { + System.out.println("will call subscriber\n"); +// subscriber.onStart(); + //onSubscribe来call这个subscriber + onSubscribe.call(subscriber); + } +} diff --git a/src/com/blankj/custom/rxjava/Observer.java b/src/com/blankj/custom/rxjava/Observer.java new file mode 100644 index 00000000..ce631dd1 --- /dev/null +++ b/src/com/blankj/custom/rxjava/Observer.java @@ -0,0 +1,9 @@ +package com.blankj.custom.rxjava; + +public interface Observer { + void onCompleted(); + + void onError(Throwable t); + + void onNext(T var1); +} diff --git a/src/com/blankj/custom/rxjava/Subscriber.java b/src/com/blankj/custom/rxjava/Subscriber.java new file mode 100644 index 00000000..d05c5a81 --- /dev/null +++ b/src/com/blankj/custom/rxjava/Subscriber.java @@ -0,0 +1,7 @@ +package com.blankj.custom.rxjava; + +public abstract class Subscriber implements Observer { + //抽象类可以抽象方法,或者具体实现,此处为具体实现 +// public void onStart() { +// } +} diff --git a/src/com/blankj/custom/rxjava/Test.java b/src/com/blankj/custom/rxjava/Test.java new file mode 100644 index 00000000..4f782f36 --- /dev/null +++ b/src/com/blankj/custom/rxjava/Test.java @@ -0,0 +1,34 @@ +package com.blankj.custom.rxjava; + +public class Test { + public static void main(String[] args) { + Observable.create(new Observable.OnSubscribe() { + //实例化接口实现类,需要override + @Override + public void call(Subscriber subscriber) { + System.out.println("call method execute\n"); + for (int i = 0; i < 10; i++) { + System.out.println("Prepare data " + i); + subscriber.onNext(i); + } + subscriber.onCompleted(); + } + }).subscribe(new Subscriber() { + //实例化接口实现类,需要override + @Override + public void onCompleted() { + System.out.println("onCompleted"); + } + + @Override + public void onError(Throwable t) { + + } + + @Override + public void onNext(Integer var1) { + System.out.println("Received data " + var1); + } + }); + } +} diff --git a/src/com/blankj/custom/sort/BubbleSort.java b/src/com/blankj/custom/sort/BubbleSort.java new file mode 100644 index 00000000..d9a15c98 --- /dev/null +++ b/src/com/blankj/custom/sort/BubbleSort.java @@ -0,0 +1,31 @@ +package com.blankj.custom.sort; + +/** + * Created by laileon on 2017/7/20. + */ + +//核心:冒泡,持续比较相邻元素,大的挪到后面,因此 {大的会逐步往后挪},故称之为冒泡。 +//时间:平均最坏O(n2),空间O(1) +//冒泡是把最大依次往后,选择是把最小依次放前 +public class BubbleSort { + public static void main(String[] args) { + int[] unsortedArray = new int[]{5,6,2,7,9,0,1}; + bubblesort(unsortedArray); + System.out.println("After sort: "); + for (int item : unsortedArray){ + System.out.println(item + " "); + } + } + + private static void bubblesort(int[] unsortedArray) { + int len = unsortedArray.length; + for (int i = 0; i < len; i++) { + //运行一次后最大的被挪到最后 + for (int j = 1; j < len - i; j++) { + if (unsortedArray[j - 1] > unsortedArray[j]){ + Utils.swap(j - 1, j, unsortedArray); + } + } + } + } +} diff --git a/src/com/blankj/custom/sort/InsertionSort.java b/src/com/blankj/custom/sort/InsertionSort.java new file mode 100644 index 00000000..0df2fbb6 --- /dev/null +++ b/src/com/blankj/custom/sort/InsertionSort.java @@ -0,0 +1,34 @@ +package com.blankj.custom.sort; + +/** + * Created by laileon on 2017/7/20. + */ +//核心:通过构建有序序列,对于未排序序列,在已排序序列中从后向前扫描(对于单向链表则只能从前往后遍历), +// 找到相应位置并插入。实现上通常使用in-place排序(需用到O(1)的额外空间) + +// “核心:基于插入排序,使数组中任意间隔为h的元素都是有序的,即将全部元素分为h个区域使用插入排序。 +// 其实现可类似于插入排序但使用不同增量。更高效的原因是它权衡了子数组的规模和有序性。 + +public class InsertionSort { + public static void main(String[] args) { + int[] unsortedArray = new int[]{5,6,2,7,9,0,11}; + insertionSort(unsortedArray); + System.out.println("After sort: "); + for (int item : unsortedArray){ + System.out.println(item + " "); + } + } + + private static void insertionSort(int[] unsortedArray) { + int len = unsortedArray.length; + for (int i = 0; i < len; i++) { + //右边将作比较的数 +// int temp = unsortedArray[i]; + while (i > 0 && unsortedArray[i - 1] > unsortedArray[i]){ + Utils.swap(i - 1, i, unsortedArray); + i --; + } +// unsortedArray[i] = temp; + } + } +} diff --git a/src/com/blankj/custom/sort/MergeSort.java b/src/com/blankj/custom/sort/MergeSort.java new file mode 100644 index 00000000..cb9130b3 --- /dev/null +++ b/src/com/blankj/custom/sort/MergeSort.java @@ -0,0 +1,62 @@ +package com.blankj.custom.sort; + +//时间复杂度为O(N log N ), 使用了等长的辅助数组,空间复杂度为O(N) +//将两个有序对数组归并成一个更大的有序数组。通常做法为递归排序,并将两个不同的有序数组归并到第三个数组中。 +// 先来看看动图,归并排序是一种典型的分治应用 + + +//“快排的实现我们可以发现其与『归并排序』的区别主要有如下两点: +// +//归并排序将数组分成两个子数组分别排序,并将有序的子数组归并以将整个数组排序。递归调用发生在处理整个数组之前。 +//快速排序将一个数组分成两个子数组并对这两个子数组独立地排序,两个子数组有序时整个数组也就有序了。递归调用发生在处理整个数组之后。” + +import java.util.Arrays; + +public class MergeSort { + public static void merge(int[] a, int low, int mid, int high) { + int[] temp = new int[high - low + 1]; + int i = low;// 左指针 + int j = mid + 1;// 右指针 + int k = 0; + // 把较小的数先移到新数组中 + while (i <= mid && j <= high) { + if (a[i] < a[j]) { + temp[k++] = a[i++]; + } else { + temp[k++] = a[j++]; + } + } + // 把左边剩余的数移入数组 + while (i <= mid) { + temp[k++] = a[i++]; + } + // 把右边边剩余的数移入数组 + while (j <= high) { + temp[k++] = a[j++]; + } + // 把新数组中的数覆盖nums数组 + for (int k2 = 0; k2 < temp.length; k2++) { + a[k2 + low] = temp[k2]; + } + } + + public static void mergeSort(int[] a, int low, int high) { + int mid = (low + high) / 2; + if (low < high) { + // 左边 + mergeSort(a, low, mid); + // 右边 + mergeSort(a, mid + 1, high); + // 左右归并 + merge(a, low, mid, high); + System.out.println(Arrays.toString(a)); + } + + } + + public static void main(String[] args) { + int a[] = { 51, 46, 20, 18, 65, 97, 82, 30, 77, 50 }; + mergeSort(a, 0, a.length - 1); + System.out.println("排序结果:" + Arrays.toString(a)); + } +} diff --git a/src/com/blankj/custom/sort/QuickSort.java b/src/com/blankj/custom/sort/QuickSort.java new file mode 100644 index 00000000..cef51895 --- /dev/null +++ b/src/com/blankj/custom/sort/QuickSort.java @@ -0,0 +1,46 @@ +package com.blankj.custom.sort; + +public class QuickSort { + public static void main(String[] args) { + int unsortedArray[] = new int[]{6, 5, 3, 1, 8, 7, 2, 4}; + quickSort(unsortedArray); + System.out.println("After sort: "); + for (int item : unsortedArray) { + System.out.print(item + " "); + } + } + + public static void quickSort2(int[] array, int l, int u) { + for (int item : array) { + System.out.print(item + " "); + } + System.out.println(); + if (l >= u) return; + int pivot = array[l]; + int left = l + 1; + int right = u; + while (left <= right) { + while (left <= right && array[left] < pivot) { + left++; + } + while (left <= right && array[right] >= pivot) { + right--; + } + if (left > right) break; + // swap array[left] with array[right] while left <= right + int temp = array[right]; + array[right] = array[left]; + array[left] = temp; + } + /* swap the smaller with pivot */ + int temp = array[right]; + array[right] = array[l]; + array[l] = temp; + quickSort2(array, l, right - 1); + quickSort2(array, right + 1, u); + } + + public static void quickSort(int[] array) { + quickSort2(array, 0, array.length - 1); + } +} diff --git a/src/com/blankj/custom/sort/README b/src/com/blankj/custom/sort/README new file mode 100644 index 00000000..fef671a8 --- /dev/null +++ b/src/com/blankj/custom/sort/README @@ -0,0 +1,26 @@ +时间复杂度-执行时间(比较和交换次数) + +空间复杂度-所消耗的额外内存空间 +使用小堆栈或表 +使用链表或指针、数组索引来代表数据 +排序数据的副本 +对具有重键的数据(同一组数按不同键多次排序)进行排序时,需要考虑排序方法的稳定性,在非稳定性排序算法中需要稳定性时可考虑加入小索引。 + +稳定性:如果排序后文件中拥有相同键的项的相对位置不变,这种排序方式是稳定的。 + +常见的排序算法根据是否需要比较可以分为如下几类: + +Comparison Sorting: +Bubble Sort +Selection Sort +Insertion Sort +Shell Sort +Merge Sort +Quck Sort +Heap Sort + +Bucket Sort + +Counting Sort + +Radix Sort diff --git a/src/com/blankj/custom/sort/SelectionSort.java b/src/com/blankj/custom/sort/SelectionSort.java new file mode 100644 index 00000000..faa27b7d --- /dev/null +++ b/src/com/blankj/custom/sort/SelectionSort.java @@ -0,0 +1,39 @@ +package com.blankj.custom.sort; + +/** + * Created by laileon on 2017/7/20. + */ +//核心:不断地选择剩余元素中的最小者。 +// +// 找到数组中最小元素并将其和数组第一个元素交换位置。 +// 在剩下的元素中找到最小元素并将其与数组第二个元素交换,直至整个数组排序。 +// 性质: +// +// 比较次数=(N-1)+(N-2)+(N-3)+...+2+1~N^2/2 +// 交换次数=N +// 运行时间与输入无关 + +public class SelectionSort { + public static void main(String[] args) { + int[] unsortedArray = new int[]{5,6,2,7,9,0,11}; + selectionSort(unsortedArray); + System.out.println("After sort: "); + for (int item : unsortedArray){ + System.out.println(item + " "); + } + } + + private static void selectionSort(int[] unsortedArray) { + int len = unsortedArray.length; + for (int i = 0; i < len; i++) { + //每次最小的index经转换后一定为最前 + int min_index = i; + for (int j = i + 1; j < len; j++) { + if (unsortedArray[j] < unsortedArray[min_index]) { + min_index = j; + } + } + Utils.swap(min_index, i, unsortedArray); + } + } +} diff --git a/src/com/blankj/custom/sort/ShellSort.java b/src/com/blankj/custom/sort/ShellSort.java new file mode 100644 index 00000000..a4602fd9 --- /dev/null +++ b/src/com/blankj/custom/sort/ShellSort.java @@ -0,0 +1,43 @@ +package com.blankj.custom.sort; + +/** + * Created by laileon on 2017/7/21. + */ + +//希尔排序对直接插入排序进行了简单的改进:它通过加大插入排序中元素之间的间隔,并在这些有间隔的元素中进行插入排序,从而使数据项大跨度地移动, +// 当这些数据项排过一趟序之后,希尔排序算法减小数据项的间隔再进行排序,依次进行下去,进行这些排序时的数据项之间的间隔被称为增量, +// 习惯上用字母h来表示这个增量。 +public class ShellSort { + public static void main(String[] args) { + int[] unsortedArray = new int[]{5, 6, 2, 7, 9, 0, 11, 26, 53, 67, 48, 57, 13, 48, 32, 60, 50}; + shellSort(unsortedArray); + System.out.println("After sort: "); + for (int item : unsortedArray) { + System.out.println(item + " "); + } + } + + private static void shellSort(int[] unsortedArray) { + // 计算出最大的h值 + int h = 1; + //常用的h序列由Knuth提出,该序列从1开始,通过如下公式产生: + while (h <= unsortedArray.length / 3) { + h = h * 3 + 1; + } + while (h > 0) { + for (int i = h; i < unsortedArray.length; i += h) { + if (unsortedArray[i] < unsortedArray[i - h]) { + int tmp = unsortedArray[i]; + int j = i - h; + while (j >= 0 && unsortedArray[j] > tmp) { + unsortedArray[j + h] = unsortedArray[j]; + j -= h; + } + unsortedArray[j + h] = tmp; + } + } + // 计算出下一个h值 + h = (h - 1) / 3; + } + } +} diff --git a/src/com/blankj/custom/sort/Test.java b/src/com/blankj/custom/sort/Test.java new file mode 100644 index 00000000..ede11377 --- /dev/null +++ b/src/com/blankj/custom/sort/Test.java @@ -0,0 +1,10 @@ +package com.blankj.custom.sort; + +public class Test { + public static void main(String[] args) { + int a = 5; + int b = 10; + a = b; + System.out.println(a + " " + b); + } +} diff --git a/src/com/blankj/custom/sort/Utils.java b/src/com/blankj/custom/sort/Utils.java new file mode 100644 index 00000000..3de94474 --- /dev/null +++ b/src/com/blankj/custom/sort/Utils.java @@ -0,0 +1,12 @@ +package com.blankj.custom.sort; + +/** + * Created by laileon on 2017/7/20. + */ +public class Utils { + public static void swap(int i, int j, int[] unsortedArray){ + int temp = unsortedArray[i]; + unsortedArray[i] = unsortedArray[j]; + unsortedArray[j] = temp; + } +} diff --git a/src/com/blankj/custom/structure/DListNode.java b/src/com/blankj/custom/structure/DListNode.java new file mode 100644 index 00000000..b12bee17 --- /dev/null +++ b/src/com/blankj/custom/structure/DListNode.java @@ -0,0 +1,29 @@ +package com.blankj.custom.structure; + +/** + * Created by laileon on 2017/7/20. + */ +//双向链表 +public class DListNode { + int val; + DListNode prev, next; + + public DListNode(int val, DListNode prev, DListNode next) { + this.val = val; + this.prev = null; + this.next = null; + } + + //双向链表核心在于next和prev的交换。 + public DListNode reverseList(DListNode head) { + DListNode curr = null; + while (head != null) { + curr = head; + head = head.next; + head.next = head.prev; + head.prev = curr; + } + return curr; + } + +} diff --git a/src/com/blankj/custom/structure/Graph.java b/src/com/blankj/custom/structure/Graph.java new file mode 100644 index 00000000..1adc5379 --- /dev/null +++ b/src/com/blankj/custom/structure/Graph.java @@ -0,0 +1,32 @@ +package com.blankj.custom.structure; + +import java.util.ArrayList; + +/** + * Created by laileon on 2017/7/20. + */ +public class Graph { + //邻接矩阵 + int[][]g = new int[1][2]; + //邻接表 + class DirectGraphNode { + int label; + ArrayList neighbors; + + public DirectGraphNode(int label) { + this.label = label; + neighbors = new ArrayList(); + } + } + + //无向图 + class UndirectGraphNode { + int label; + ArrayList neighbors; + + public UndirectGraphNode(int label) { + this.label = label; + neighbors = new ArrayList(); + } + } +} diff --git a/src/com/blankj/custom/structure/ListNode.java b/src/com/blankj/custom/structure/ListNode.java new file mode 100644 index 00000000..5f3ff35b --- /dev/null +++ b/src/com/blankj/custom/structure/ListNode.java @@ -0,0 +1,28 @@ +package com.blankj.custom.structure; + +/** + * Created by laileon on 2017/7/19. + */ +//链表 插入删除o(1) +public class ListNode { + public int val; + public ListNode next; + + public ListNode(int val, ListNode next) { + this.val = val; + this.next = null; + } + + //单向链表, 从前往后反转各个结点的指针域的指向 + //非递归实现很简单,只需要遍历一遍链表,在遍历过程中,把遍历的节点依次插入到头部 + public ListNode reverseList(ListNode head) { + ListNode curr = null; + while (head != null) { //如果当前节点不为空 + curr = head; //prev后移一位 + head = head.next; //head后移一位 + head.next = curr; //head指向head后面那个 + } + return curr; + } + +} diff --git a/src/com/blankj/custom/structure/QueueInJava.java b/src/com/blankj/custom/structure/QueueInJava.java new file mode 100644 index 00000000..b47a0f26 --- /dev/null +++ b/src/com/blankj/custom/structure/QueueInJava.java @@ -0,0 +1,41 @@ +package com.blankj.custom.structure; + +import java.util.*; + +/** + * Created by laileon on 2017/7/20. + */ + +//“Java 中提供PriorityQueue类,该类是 Interface Queue 的另外一种实现,和LinkedList的区别主要在于排序行为而不是性能, +// 基于 priority heap 实现,非synchronized,故多线程下应使用PriorityBlockingQueue. 默认为自然序(小根堆), +// 需要其他排序方式可自行实现Comparator接口,选用合适的构造器初始化。使用迭代器遍历时不保证有序, +// 有序访问时需要使用Arrays.sort(pq.toArray()).” + +public class QueueInJava { + public static void main(String[] args) { + + Queue queue = new LinkedList<>(); + int size = queue.size(); + +// JDK doc 中建议使用Deque代替Stack实现栈,因为Stack继承自Vector,需要synchronized,性能略低。 + //栈 + Deque stack = new ArrayDeque<>(); + int getSize = stack.size(); + +// “Set 与 Collection 具有安全一样的接口,通常有HashSet, TreeSet 或 LinkedHashSet三种实现。 +// HashSet基于散列函数实现,无序,查询速度最快;TreeSet基于红-黑树实现,有序。” + Set hash = new HashSet<>(); + hash.add("bill"); + hash.contains("bill"); + +// “Java 的实现中 Map 是一种将对象与对象相关联的设计。常用的实现有HashMap和TreeMap, HashMap被用来快速访问, +// 而TreeMap则保证『键』始终有序。Map 可以返回键的 Set, 值的 Collection, 键值对的 Set.” + Map map = new HashMap<>(); + //遍历 + for (Map.Entry entry : map.entrySet()) { + String key = entry.getKey(); + int value = entry.getValue(); + } + } + +} diff --git a/src/com/blankj/custom/structure/TreeNode.java b/src/com/blankj/custom/structure/TreeNode.java new file mode 100644 index 00000000..48064bf4 --- /dev/null +++ b/src/com/blankj/custom/structure/TreeNode.java @@ -0,0 +1,31 @@ +package com.blankj.custom.structure; + +/** + * Created by laileon on 2017/7/20. + */ +//二叉树 + +//深度优先:先访问子节点,再访问父节点,最后访问第二个子节点。根据根节点相对于左右子节点的访问先后顺序又可细分为以下三种方式。 +// 前序(pre-order):先根后左再右 +// 中序(in-order):先左后根再右 +// 后序(post-order):先左后右再根 +//广度优先:先访问根节点,沿着树的宽度遍历子节点,直到所有节点均被访问为止。 + + +// Binary Search Tree - 二叉查找树 +// +// 一颗二叉查找树(BST)是一颗二叉树,其中每个节点都含有一个可进行比较的键及相应的值,且每个节点的键都大于等于左子树中的任意节点的键,而小于右子树中的任意节点的键。 +// +// 使用中序遍历可得到有序数组,这是二叉查找树的又一个重要特征。 + + +public class TreeNode { + public int val; + public TreeNode left, right; + + public TreeNode(int val, TreeNode left, TreeNode right) { + this.val = val; + this.left = left; + this.right = right; + } +} diff --git a/src/com/blankj/easy/_001/Practice.java b/src/com/blankj/easy/_001/Practice.java new file mode 100644 index 00000000..47bd5c9c --- /dev/null +++ b/src/com/blankj/easy/_001/Practice.java @@ -0,0 +1,27 @@ +package com.blankj.easy._001; + +import java.util.Arrays; +import java.util.HashMap; + +public class Practice { + public int[] twoSum(int[] nums, int target) { + int len = nums.length; + HashMap map = new HashMap<>(); + for (int i = 0; i < len; i++) { + // [0 , 15] [1, 10] [2, 6] [3, 2] + int num = nums[i]; + if (map.containsKey(num)) { + return new int[]{map.get(num), i}; + } + map.put(target - nums[i], i); + } + return null; + } + + public static void main(String[] args) { + Practice solution = new Practice(); + int[] nums = new int[]{2, 7, 11, 15}; + int target = 17; + System.out.println(Arrays.toString(solution.twoSum(nums, target))); + } +} diff --git a/src/com/blankj/easy/_001/Solution.java b/src/com/blankj/easy/_001/Solution.java index ff0af5f4..aaf6104a 100644 --- a/src/com/blankj/easy/_001/Solution.java +++ b/src/com/blankj/easy/_001/Solution.java @@ -26,7 +26,7 @@ public class Solution { public int[] twoSum(int[] nums, int target) { int len = nums.length; HashMap map = new HashMap<>(); - for (int i = 0; i < len; ++i) { + for (int i = 0; i < len; i++) { if (map.containsKey(nums[i])) { return new int[]{map.get(nums[i]), i}; } @@ -38,7 +38,7 @@ public int[] twoSum(int[] nums, int target) { public static void main(String[] args) { Solution solution = new Solution(); int[] nums = new int[]{2, 7, 11, 15}; - int target = 9; + int target = 17; System.out.println(Arrays.toString(solution.twoSum(nums, target))); } } diff --git a/src/com/blankj/medium/_002/Solution.java b/src/com/blankj/medium/_002/Solution.java index 6444943b..cda7acb7 100644 --- a/src/com/blankj/medium/_002/Solution.java +++ b/src/com/blankj/medium/_002/Solution.java @@ -34,9 +34,11 @@ public ListNode addTwoNumbers(ListNode l1, ListNode l2) { public static void main(String[] args) { Solution solution = new Solution(); + System.out.println(627 / 10); + System.out.println(627 % 10); ListNode.print(solution.addTwoNumbers( ListNode.createTestData("[2,4,3]"), - ListNode.createTestData("[5,6,4]") + ListNode.createTestData("[8,4,4]") )); } } diff --git a/src/com/blankj/medium/_017/Solution.java b/src/com/blankj/medium/_017/Solution.java index f7e8c0c8..c3109ef2 100644 --- a/src/com/blankj/medium/_017/Solution.java +++ b/src/com/blankj/medium/_017/Solution.java @@ -13,7 +13,7 @@ * */ public class Solution { -// private static String[] map = new String[]{"abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}; +// private staticProxy String[] map = new String[]{"abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}; // // public List letterCombinations(String digits) { // if (digits.length() == 0) return Collections.emptyList();