diff --git a/group01/954958168/.gitignore b/group01/954958168/.gitignore new file mode 100644 index 0000000000..e8b4e006b1 --- /dev/null +++ b/group01/954958168/.gitignore @@ -0,0 +1,9 @@ +build +target/ +*.class +# ide +.settings/ +.project +.classpath +.idea/ +*.iml diff --git a/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/LinkedList.java b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/LinkedList.java index 504e73580b..b4e5fe5027 100644 --- a/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/LinkedList.java +++ b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/LinkedList.java @@ -84,7 +84,7 @@ public Object[] toArray() { Object[] objects = new Object[size]; Node first = head.next; int pos = 0; - while (first!= null) { + while (first != null) { objects[pos++] = first.data; first = first.next; } @@ -126,4 +126,196 @@ private Node(Object data) { this.data = data; } } + + /** + * 把该链表逆置 + * 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse() { + Node newHead = new Node(null); + Node node = head.next; + while (node != null) { + Node temp = node.next; + node.next = newHead.next; + newHead.next = node; + node = temp; + } + head = newHead; + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + */ + public void removeFirstHalf() { + int removeLen = size / 2; + if (size <= 1) { + head.next = null; + size = 0; + return; + } + for (int i = 0; i < removeLen; i++) { + Node point = head.next; + head.next = point.next; + point.next = null; + size--; + } + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * + * @param i + * @param length + */ + public void remove(int i, int length) { + if (i < 0 || i >= size || length < 1) throw new IndexOutOfBoundsException("索引超出范围"); + int endIndex = Math.min(i + length, size); + Node preNode = head; + Node endNode = head.next; + for (int index = 0; index < endIndex; index++) { + if (index < i) { + preNode = endNode; + } + endNode = endNode.next; + } + + preNode.next = endNode; + size = size - (endIndex - i); + } + + /** + * 假定当前链表和list均包含已升序排列的整数 + * 从当前链表中取出那些list所指定的元素 + * 例如当前链表 = 11->101->201->301->401->501->601->701 + * listB = 1->3->4->6 + * 返回的结果应该是[101,301,401,601] + * + * @param list + */ + public int[] getElements(LinkedList list) { + if (list == null) return new int[0]; + Iterator iterator = list.iterator(); + int[] result = new int[list.size()]; + int index = 0; + while (iterator.hasNext()) { + Integer next = (Integer) iterator.next(); + result[index] = (Integer) this.get(next); + index++; + } + return result; + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 从当前链表中中删除在list中出现的元素 + * + * @param list + */ + + public void subtract(LinkedList list) { + if (list == null) return; + Iterator iterator = this.iterator(); + while (iterator.hasNext()) { + Object element = iterator.next(); + if (contain(element, list)) { + iterator.remove(); + } + } + } + + private boolean contain(Object element, LinkedList list) { + Iterator iterator = list.iterator(); + while (iterator.hasNext()) { + Object next = iterator.next(); + if (next == element) return true; + } + return false; + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues() { + Node pre = head; + Node cur = head.next; + while (cur != null) { + if (pre.data == cur.data) { + Node node = cur.next; + while (node != null && node.data == pre.data) { + node = node.next; + size--; + } + pre.next = node; + cur = node; + size--; + } else { + pre = cur; + cur = cur.next; + } + } + + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + * + * @param min + * @param max + */ + public void removeRange(int min, int max) { + if (min >= max) return; + Node cur = head; + Node start = null; + Node end = null; + Integer startIndex = null; + Integer endIndex = size - 1; + Integer index = -1; + while (cur.next != null) { + if (start == null && (Integer) cur.next.data > min) { + start = cur; + startIndex = index; + } + if ((Integer) cur.next.data >= max) { + end = cur.next; + endIndex = index; + break; + } + cur = cur.next; + index++; + } + if (start != null) { + start.next = end; + size = size - (endIndex - startIndex); + } + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * + * @param list + */ + public LinkedList intersection(LinkedList list) { + if (list == null) return this; + LinkedList intersection = new LinkedList(); + Node node1 = this.head.next; + Node node2 = list.head.next; + while (node1 != null && node2 != null) { + if((Integer)node1.data < (Integer)node2.data) { + node1 = node1.next; + } else if((Integer)node1.data > (Integer)node2.data) { + node2 = node2.next; + } else { + intersection.add(node1.data); + node1 = node1.next; + node2 = node2.next; + } + } + + return intersection; + } } diff --git a/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/LinkListTest.java b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/LinkListTest.java index b1bfc6f1b8..508eaba5f9 100644 --- a/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/LinkListTest.java +++ b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/LinkListTest.java @@ -19,6 +19,8 @@ public void init() { linkedList.add(1); linkedList.add(2); linkedList.add(3); + linkedList.add(4); + linkedList.add(5); } @Test @@ -78,4 +80,104 @@ public void testIterator() { } Assert.assertArrayEquals(new Object[]{}, linkedList.toArray()); } + + @Test + public void testReverse() { + linkedList.reverse(); + Assert.assertArrayEquals(new Object[]{3, 2, 1}, linkedList.toArray()); + } + + @Test + public void testRemoveFirstHalf() { + linkedList.removeFirstHalf(); + Assert.assertArrayEquals(new Object[]{2, 3}, linkedList.toArray()); + } + + @Test + public void testRangeRemove() { + linkedList.remove(1, 4); + Assert.assertArrayEquals(new Object[]{1}, linkedList.toArray()); + } + + @Test + public void testGetElements() { + LinkedList sub = new LinkedList(); + sub.add(1); + sub.add(3); + sub.add(4); + int[] result = linkedList.getElements(sub); + Assert.assertArrayEquals(new int[]{2, 4, 5}, result); + } + + @Test + public void testSubtract() { + LinkedList sub = new LinkedList(); + sub.add(1); + sub.add(2); + sub.add(10); + linkedList.subtract(sub); + Assert.assertArrayEquals(new Object[]{3, 4, 5}, linkedList.toArray()); + } + + @Test + public void testRemoveDuplicateValues() { + LinkedList list = new LinkedList(); + list.add(1); + list.add(2); + list.add(2); + list.add(2); + list.add(3); + list.add(3); + list.add(4); + list.add(5); + list.add(6); + list.add(6); + list.add(7); + list.add(7); + list.add(7); + list.add(7); + list.add(7); + list.removeDuplicateValues(); + Assert.assertArrayEquals(new Object[]{1, 2, 3, 4, 5, 6, 7}, list.toArray()); + } + + @Test + public void testRemoveRange() { + LinkedList list = new LinkedList(); + list.add(1); + list.add(2); + list.add(2); + list.add(3); + list.add(4); + list.add(5); + list.add(6); + list.add(7); + list.add(7); + list.add(8); + list.removeRange(1, 4); + Assert.assertArrayEquals(new Object[]{1, 4, 5, 6, 7, 7, 8}, list.toArray()); + } + + @Test + public void testIntersection() { + LinkedList list1 = new LinkedList(); + list1.add(1); + list1.add(3); + list1.add(5); + list1.add(7); + list1.add(9); + LinkedList list2 = new LinkedList(); + list2.add(3); + list2.add(4); + list2.add(5); + list2.add(6); + list2.add(7); + list2.add(8); + list2.add(10); + list2.add(11); + list2.add(12); + LinkedList intersection = list1.intersection(list2); + Assert.assertArrayEquals(new Object[]{3, 5, 7}, intersection.toArray()); + } + } diff --git a/group01/954958168/class02/LiteStruts/pom.xml b/group01/954958168/class02/LiteStruts/pom.xml index 9a962fe54c..40ba7c66b6 100644 --- a/group01/954958168/class02/LiteStruts/pom.xml +++ b/group01/954958168/class02/LiteStruts/pom.xml @@ -8,11 +8,6 @@ lite-struts 1.0.0-SNAPSHOT - - UTF-8 - 1.8 - - junit @@ -29,6 +24,19 @@ commons-lang3 3.5 - + + + + liteStruts + + true + + + UTF-8 + 1.8 + 1.8 + + + \ No newline at end of file diff --git a/group01/954958168/class03/MultiThreadDownload/pom.xml b/group01/954958168/class03/MultiThreadDownload/pom.xml new file mode 100644 index 0000000000..4d94b30e33 --- /dev/null +++ b/group01/954958168/class03/MultiThreadDownload/pom.xml @@ -0,0 +1,32 @@ + + + 4.0.0 + + com.aaront.exercise + multithread-download + 1.0.0-SNAPSHOT + + + junit + junit + 4.12 + + + + + + multiThreadDownload + + true + + + UTF-8 + 1.8 + 1.8 + + + + + \ No newline at end of file diff --git a/group01/954958168/class03/MultiThreadDownload/src/main/java/com/aaront/exercise/DownloadThread.java b/group01/954958168/class03/MultiThreadDownload/src/main/java/com/aaront/exercise/DownloadThread.java new file mode 100644 index 0000000000..8dcf538f42 --- /dev/null +++ b/group01/954958168/class03/MultiThreadDownload/src/main/java/com/aaront/exercise/DownloadThread.java @@ -0,0 +1,32 @@ +package com.aaront.exercise; + +import com.aaront.exercise.api.Connection; + +import java.io.IOException; + +public class DownloadThread extends Thread { + + Connection conn; + int startPos; + int endPos; + byte[] content; + + public DownloadThread(Connection conn, int startPos, int endPos) { + + this.conn = conn; + this.startPos = startPos; + this.endPos = endPos; + } + + public void run() { + try { + content = conn.read(startPos, endPos); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public byte[] getContent() { + return this.content; + } +} \ No newline at end of file diff --git a/group01/954958168/class03/MultiThreadDownload/src/main/java/com/aaront/exercise/FileDownloader.java b/group01/954958168/class03/MultiThreadDownload/src/main/java/com/aaront/exercise/FileDownloader.java new file mode 100644 index 0000000000..128292ea8e --- /dev/null +++ b/group01/954958168/class03/MultiThreadDownload/src/main/java/com/aaront/exercise/FileDownloader.java @@ -0,0 +1,90 @@ +package com.aaront.exercise; + + +import com.aaront.exercise.api.Connection; +import com.aaront.exercise.api.ConnectionManager; +import com.aaront.exercise.api.DownloadListener; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class FileDownloader { + + String url; + + DownloadListener listener; + + ConnectionManager cm; + + + public FileDownloader(String _url) { + this.url = _url; + + } + + public void execute() { + // 在这里实现你的代码, 注意: 需要用多线程实现下载 + // 这个类依赖于其他几个接口, 你需要写这几个接口的实现代码 + // (1) ConnectionManager , 可以打开一个连接,通过Connection可以读取其中的一段(用startPos, endPos来指定) + // (2) DownloadListener, 由于是多线程下载, 调用这个类的客户端不知道什么时候结束,所以你需要实现当所有 + // 线程都执行完以后, 调用listener的notifiedFinished方法, 这样客户端就能收到通知。 + // 具体的实现思路: + // 1. 需要调用ConnectionManager的open方法打开连接, 然后通过Connection.getContentLength方法获得文件的长度 + // 2. 至少启动3个线程下载, 注意每个线程需要先调用ConnectionManager的open方法 + // 然后调用read方法, read方法中有读取文件的开始位置和结束位置的参数, 返回值是byte[]数组 + // 3. 把byte数组写入到文件中 + // 4. 所有的线程都下载完成以后, 需要调用listener的notifiedFinished方法 + + // 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。 + + Connection conn = cm.open(this.url); + int length = conn.getContentLength(); + conn.close(); + List threads = new ArrayList<>(); + int i; + for (i = 0; i < 3; i++) { + DownloadThread thread = new DownloadThread(cm.open(this.url), i * (length / 3), (i + 1) * (length / 3) - 1); + threads.add(thread); + thread.start(); + } + if (i * (length / 3) < length) { + DownloadThread thread = new DownloadThread(cm.open(this.url), i * (length / 3), length - 1); + threads.add(thread); + thread.start(); + } + + try { + for (DownloadThread thread : threads) { + thread.join(); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + + try (FileOutputStream fos = new FileOutputStream(new File("temp.jpg"))) { + for(DownloadThread thread : threads) { + fos.write(thread.getContent()); + } + } catch (IOException e) { + e.printStackTrace(); + } + + this.listener.notifyFinished(); + } + + public void setListener(DownloadListener listener) { + this.listener = listener; + } + + public void setConnectionManager(ConnectionManager ucm) { + this.cm = ucm; + } + + public DownloadListener getListener() { + return this.listener; + } + +} diff --git a/group01/954958168/class03/MultiThreadDownload/src/main/java/com/aaront/exercise/FileDownloaderTest.java b/group01/954958168/class03/MultiThreadDownload/src/main/java/com/aaront/exercise/FileDownloaderTest.java new file mode 100644 index 0000000000..6f75b3cd6c --- /dev/null +++ b/group01/954958168/class03/MultiThreadDownload/src/main/java/com/aaront/exercise/FileDownloaderTest.java @@ -0,0 +1,41 @@ +package com.aaront.exercise; + +import com.aaront.exercise.api.ConnectionManager; +import com.aaront.exercise.impl.ConnectionManagerImpl; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class FileDownloaderTest { + boolean downloadFinished = false; + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testDownload() { + String url = "http://localhost:8080/test.jpg"; + FileDownloader downloader = new FileDownloader(url); + ConnectionManager cm = new ConnectionManagerImpl(); + downloader.setConnectionManager(cm); + downloader.setListener(() -> downloadFinished = true); + downloader.execute(); + + // 等待多线程下载程序执行完毕 + while (!downloadFinished) { + try { + System.out.println("还没有下载完成,休眠五秒"); + //休眠5秒 + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + System.out.println("下载完成!"); + } +} diff --git a/group01/954958168/class03/MultiThreadDownload/src/main/java/com/aaront/exercise/api/Connection.java b/group01/954958168/class03/MultiThreadDownload/src/main/java/com/aaront/exercise/api/Connection.java new file mode 100644 index 0000000000..64e0573bf5 --- /dev/null +++ b/group01/954958168/class03/MultiThreadDownload/src/main/java/com/aaront/exercise/api/Connection.java @@ -0,0 +1,26 @@ +package com.aaront.exercise.api; + +import java.io.IOException; + +public interface Connection { + /** + * 给定开始和结束位置, 读取数据, 返回值是字节数组 + * + * @param startPos 开始位置, 从0开始 + * @param endPos 结束位置 + * @return + */ + public byte[] read(int startPos, int endPos) throws IOException; + + /** + * 得到数据内容的长度 + * + * @return + */ + public int getContentLength(); + + /** + * 关闭连接 + */ + public void close(); +} diff --git a/group01/954958168/class03/MultiThreadDownload/src/main/java/com/aaront/exercise/api/ConnectionException.java b/group01/954958168/class03/MultiThreadDownload/src/main/java/com/aaront/exercise/api/ConnectionException.java new file mode 100644 index 0000000000..d70dffce34 --- /dev/null +++ b/group01/954958168/class03/MultiThreadDownload/src/main/java/com/aaront/exercise/api/ConnectionException.java @@ -0,0 +1,16 @@ +package com.aaront.exercise.api; + +public class ConnectionException extends RuntimeException { + + public ConnectionException(String message) { + super(message); + } + + public ConnectionException(String message, Throwable cause) { + super(message, cause); + } + + public ConnectionException(Throwable cause) { + super(cause); + } +} diff --git a/group01/954958168/class03/MultiThreadDownload/src/main/java/com/aaront/exercise/api/ConnectionManager.java b/group01/954958168/class03/MultiThreadDownload/src/main/java/com/aaront/exercise/api/ConnectionManager.java new file mode 100644 index 0000000000..7d7e027b02 --- /dev/null +++ b/group01/954958168/class03/MultiThreadDownload/src/main/java/com/aaront/exercise/api/ConnectionManager.java @@ -0,0 +1,10 @@ +package com.aaront.exercise.api; + +public interface ConnectionManager { + /** + * 给定一个url , 打开一个连接 + * @param url + * @return + */ + public Connection open(String url) throws ConnectionException; +} diff --git a/group01/954958168/class03/MultiThreadDownload/src/main/java/com/aaront/exercise/api/DownloadListener.java b/group01/954958168/class03/MultiThreadDownload/src/main/java/com/aaront/exercise/api/DownloadListener.java new file mode 100644 index 0000000000..3a1defa2ca --- /dev/null +++ b/group01/954958168/class03/MultiThreadDownload/src/main/java/com/aaront/exercise/api/DownloadListener.java @@ -0,0 +1,5 @@ +package com.aaront.exercise.api; + +public interface DownloadListener { + public void notifyFinished(); +} diff --git a/group01/954958168/class03/MultiThreadDownload/src/main/java/com/aaront/exercise/impl/ConnectionImpl.java b/group01/954958168/class03/MultiThreadDownload/src/main/java/com/aaront/exercise/impl/ConnectionImpl.java new file mode 100644 index 0000000000..5ad971c7c3 --- /dev/null +++ b/group01/954958168/class03/MultiThreadDownload/src/main/java/com/aaront/exercise/impl/ConnectionImpl.java @@ -0,0 +1,42 @@ +package com.aaront.exercise.impl; + +import com.aaront.exercise.api.Connection; +import com.aaront.exercise.api.ConnectionException; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; + +public class ConnectionImpl implements Connection { + + private FileInputStream fis; + private File file; + + public ConnectionImpl(String source) throws FileNotFoundException { + file = new File(getClass().getClassLoader().getResource(source).getFile()); + fis = new FileInputStream(file); + } + + @Override + public byte[] read(int startPos, int endPos) throws IOException { + fis.skip(startPos); + byte[] content = new byte[endPos - startPos + 1]; + fis.read(content, 0, content.length); + return content; + } + + @Override + public int getContentLength() { + return (int)file.length(); + } + + @Override + public void close() { + try { + fis.close(); + } catch (IOException e) { + throw new ConnectionException("连接关闭失败"); + } + } +} \ No newline at end of file diff --git a/group01/954958168/class03/MultiThreadDownload/src/main/java/com/aaront/exercise/impl/ConnectionManagerImpl.java b/group01/954958168/class03/MultiThreadDownload/src/main/java/com/aaront/exercise/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..a80c293176 --- /dev/null +++ b/group01/954958168/class03/MultiThreadDownload/src/main/java/com/aaront/exercise/impl/ConnectionManagerImpl.java @@ -0,0 +1,28 @@ +package com.aaront.exercise.impl; + +import com.aaront.exercise.api.Connection; +import com.aaront.exercise.api.ConnectionException; +import com.aaront.exercise.api.ConnectionManager; + +import java.io.FileNotFoundException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ConnectionManagerImpl implements ConnectionManager { + + @Override + public Connection open(String url) throws ConnectionException { + try { + return new ConnectionImpl(parse(url)); + } catch (FileNotFoundException e) { + throw new ConnectionException("创建连接失败"); + } + } + + private String parse(String url) { + String pattern = "(http|https)://[a-zA-Z0-9]+:[0-9]+/([a-zA-Z0-9.]+)"; + Matcher compile = Pattern.compile(pattern).matcher(url); + if(!compile.matches()) throw new ConnectionException("资源url不合法"); + return compile.group(2); + } +} diff --git a/group01/954958168/class03/MultiThreadDownload/src/main/resources/test.jpg b/group01/954958168/class03/MultiThreadDownload/src/main/resources/test.jpg new file mode 100644 index 0000000000..0eb7a002d8 Binary files /dev/null and b/group01/954958168/class03/MultiThreadDownload/src/main/resources/test.jpg differ