From 6af890a053ba7363ebf4012ae539c5fff3fe473b Mon Sep 17 00:00:00 2001 From: xiaozi Date: Tue, 28 Mar 2017 19:55:33 +0800 Subject: [PATCH] Third --- .../coding2017/basic/LinkedList.java | 386 +++++++++++++----- .../xiaozi123/coding2017/thirdWork/.gitignore | 27 ++ .../coding2017/thirdWork/DownloadThread.java | 44 ++ .../coding2017/thirdWork/FileDownloader.java | 117 ++++++ .../thirdWork/FileDownloaderTest.java | 62 +++ .../coding2017/thirdWork/api/Connection.java | 24 ++ .../thirdWork/api/ConnectionException.java | 7 + .../thirdWork/api/ConnectionManager.java | 10 + .../thirdWork/api/DownloadListener.java | 5 + .../thirdWork/impl/ConnectionImpl.java | 79 ++++ .../thirdWork/impl/ConnectionManagerImpl.java | 17 + ...7\347\253\240\345\234\260\345\235\200.txt" | 1 + 12 files changed, 669 insertions(+), 110 deletions(-) create mode 100644 group24/1054283210/src/com/github/xiaozi123/coding2017/thirdWork/.gitignore create mode 100644 group24/1054283210/src/com/github/xiaozi123/coding2017/thirdWork/DownloadThread.java create mode 100644 group24/1054283210/src/com/github/xiaozi123/coding2017/thirdWork/FileDownloader.java create mode 100644 group24/1054283210/src/com/github/xiaozi123/coding2017/thirdWork/FileDownloaderTest.java create mode 100644 group24/1054283210/src/com/github/xiaozi123/coding2017/thirdWork/api/Connection.java create mode 100644 group24/1054283210/src/com/github/xiaozi123/coding2017/thirdWork/api/ConnectionException.java create mode 100644 group24/1054283210/src/com/github/xiaozi123/coding2017/thirdWork/api/ConnectionManager.java create mode 100644 group24/1054283210/src/com/github/xiaozi123/coding2017/thirdWork/api/DownloadListener.java create mode 100644 group24/1054283210/src/com/github/xiaozi123/coding2017/thirdWork/impl/ConnectionImpl.java create mode 100644 group24/1054283210/src/com/github/xiaozi123/coding2017/thirdWork/impl/ConnectionManagerImpl.java create mode 100644 "group24/1054283210/src/com/github/xiaozi123/coding2017/thirdWork/\346\226\207\347\253\240\345\234\260\345\235\200.txt" diff --git a/group24/1054283210/src/com/github/xiaozi123/coding2017/basic/LinkedList.java b/group24/1054283210/src/com/github/xiaozi123/coding2017/basic/LinkedList.java index 66ab1e0300..9b63437dd2 100644 --- a/group24/1054283210/src/com/github/xiaozi123/coding2017/basic/LinkedList.java +++ b/group24/1054283210/src/com/github/xiaozi123/coding2017/basic/LinkedList.java @@ -1,141 +1,307 @@ package com.github.xiaozi123.coding2017.basic; +import java.util.HashSet; import java.util.NoSuchElementException; - -import jdk.nashorn.internal.ir.IndexNode; +import java.util.Set; public class LinkedList implements List { - - private Node head; + private int size; - - private Node node(Object o) { - Node now=new Node(); - now.data=o; - now.next=null; - size++; - return now; + private Node head; + private Node last; + + public void add(Object o) { + addLast(o); } - - public void add(Object o){ - if (head==null) { - head=node(o); + + public void addLast(Object o) { + final Node l = last; + final Node newNode = new Node(o, null); + last = newNode; + if (l == null) + head = newNode; + else + l.next = newNode; + size ++; + } + + public void add(int index , Object o) { + makeSure(index); + if (index == 0){ + addFirst(o); + }else { + final Node preNode = getPreNode(index); + final Node nextNode = preNode.next; + final Node newNode = new Node(o, nextNode); + preNode.next = newNode; } - else { - addLast(o); + } + + public void addFirst(Object o){ + final Node h = head; + final Node newNode = new Node(o, head); + head = newNode; + if (h == null) + last = newNode; + size++; + } + + private Node getPreNode(int index) { + Node preNode = head; + for (int i = 0 ; i != index - 1 && preNode != null; ++i) { + preNode = preNode.next; } - + return preNode; } - public void add(int index , Object o){ - if (index<0||index>size) { - throw new IndexOutOfBoundsException("OutOfBound"); - }else if (index==0) { - addFirst(o); - }else if (index==size+1) { - addLast(o); - }else{ - Node beforeNode=head; - for (int i = 0; i < index-1; i++) { - beforeNode=beforeNode.next; + + private void makeSure(int index) { + if (index >= size || index < 0) + throw new IndexOutOfBoundsException(); + } + + public Object get(int index) { + Object targetData = null; + makeSure(index); + Iterator iterator = iterator(); + for (int i = 0; iterator.hasNext(); ++i, iterator.next()) { + if (i == index) { + targetData = iterator.next(); + break; } - Node addNode=node(o); - addNode.next=beforeNode.next; - beforeNode.next=addNode; - } + } + return targetData; } - - - public Object get(int index){ - if (index<0||index>size) { - throw new IndexOutOfBoundsException("OutOfBound"); + + public Object remove(int index) { + if (size <= 0) + throw new IndexOutOfBoundsException(); + makeSure(index); + Object oldData; + if (index == 0) { + oldData = removeFirst(); + } else if (index == size - 1) { + oldData = removeLast(); } else { - Node indexNode=head; - for (int i = 0; i < index; i++) { - indexNode=indexNode.next; - } - return indexNode.data; + final Node preNode = getPreNode(index); + final Node nextNode = preNode.next.next; + oldData = preNode.next.data; + preNode.next = nextNode; + size --; } - + return oldData; } - public Object remove(int index){ - if (index<0||index>size) { - throw new IndexOutOfBoundsException("OutOfBound"); - }else if(index==0){ - return removeFirst(); - }else if(index==size){ - return removeLast(); - - }else{ - Node beforeNode=head; - for (int i = 0; i < index-1; i++) { - beforeNode=beforeNode.next; - } - - Node indexNode=head; - for (int i = 0; i < index; i++) { - indexNode=indexNode.next; - } - beforeNode.next=indexNode.next; - indexNode.next=null; - size--; - return indexNode.data; - } + + public Object removeFirst() { + Object oldData; + final Node h = head.next; + oldData = head.data; + head = h; + size --; + return oldData; + } + + public Object removeLast() { + Object oldData; + final Node l = getPreNode(size); + oldData = last.data; + last = l; + size --; + return oldData; } public int size(){ return size; } - - public void addFirst(Object o){ - Node headNode=node(o); - headNode.data=o; - headNode.next=head.next; - head=headNode; - + + + public Iterator iterator() { + return new LinkedListIterator(); + } + + private class LinkedListIterator implements Iterator{ + private Node pointer = head; + private int nextIndex = 0; + + @Override + public boolean hasNext() { + return nextIndex < size; + } + + @Override + public Object next() { + if (!hasNext()) + throw new NoSuchElementException(); + Object nodeData = pointer.data; + pointer = pointer.next; + nextIndex ++; + return nodeData; + } + } + + private static class Node { + Object data; + Node next; + Node(Object data, Node next) { + this.data = data; + this.next = next; + } } - public void addLast(Object o){ - Node tailNode=head; - while(tailNode.next!=null){ - tailNode=tailNode.next; - } - Node lastNode=node(o); - tailNode.next=lastNode; - } - public Object removeFirst(){ - if (head==null) { - throw new NoSuchElementException(); - } - Object temp= head.data; - head=head.next; - size--; - return temp; - } - public Object removeLast(){ - if (head==null) { - throw new NoSuchElementException(); - } - Node newNode=head; - while(newNode.next.next!=null){ - newNode=newNode.next; - } - Node lastNode=newNode.next; - newNode.next=null; - size--; - return lastNode.data; - + /** + * 把该链表逆置 + * 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse() { + Node node = last; + Node preNode = head; + last = head; + head = node; + node = preNode.next; + Node nextNode; + preNode.next = null; + while (node != null) { + nextNode = node.next; + node.next = preNode; + preNode = node; + node = nextNode; + } } - public Iterator iterator(){ - return null; + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + */ + public void removeFirstHalf() { + int half = size / 2; + Node node = head; + while (half != 0 ) { + head = head.next; + node.next = null; + node = head; + half --; + } } + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * @param i + * @param length + */ + public void remove(int i, int length) { + if (i + length != size) + makeSure(i + length); + Node node = head; + Node preNode = head; + + if (i > 0) { + for (int j = 0; j < i; ++j) { + preNode = node; + node = node.next; + } + } + + Node tempNode; + for (int j = 0; j < length; ++j) { + tempNode = node.next; + node.next = null; + node = tempNode; + size --; + } + + if (i == 0) { + head = node; + } else { + preNode.next = node; + } + } + /** + * 假定当前链表和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) { + int array[] = new int[list.size()]; + int index = 0; + int i = 0; + Iterator iterator = list.iterator(); + while (iterator.hasNext()) { + i = (int)iterator.next(); + makeSure(i); + array[index ++] = (int)get(i); + } + return array; + } - private static class Node{ - Object data; - Node next; - + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 从当前链表中中删除在list中出现的元素 + * + * (适用于list 是 List的真子集) + * @param list + */ + public void subtract(LinkedList list) { + Iterator iterator = list.iterator(); + int index = 0; + Object element; + while (iterator.hasNext()) { + element = iterator.next(); + for (int i = index; i < size; ++i) { + if (element == get(i)) { + index = i; + break; + } + } + remove(index); + } } + + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * @param list + */ + public LinkedList intersection( LinkedList list) { + LinkedList newLink = new LinkedList(); + Iterator it1 = iterator(); + Iterator it2 = list.iterator(); + int element1 = (int)it1.next(); + int element2 = (int)it2.next(); + while (it1.hasNext() && it2.hasNext()) { + if (element1 < element2) { + newLink.add(element1); + element1 = (int) it1.next(); + } else { + newLink.add(element2); + element2 = (int) it2.next(); + } + } + + while (it1.hasNext()) { + if (element1 == 0) + element1 = (int)it1.next(); + newLink.add(element1); + element1 = 0; + } + while (it2.hasNext()) { + if (element2 == 0) + element2 = (int)it2.next(); + newLink.add(element2); + element2 = 0; + } + if (element1 < element2) + newLink.add(element2); + else if (element2 < element1) + newLink.add(element1); + + return newLink; + } + public static void main(String[] args) { LinkedList linkedList=new LinkedList(); diff --git a/group24/1054283210/src/com/github/xiaozi123/coding2017/thirdWork/.gitignore b/group24/1054283210/src/com/github/xiaozi123/coding2017/thirdWork/.gitignore new file mode 100644 index 0000000000..2c93a035dc --- /dev/null +++ b/group24/1054283210/src/com/github/xiaozi123/coding2017/thirdWork/.gitignore @@ -0,0 +1,27 @@ +*.class +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +#ide config +.metadata +.recommenders +.idea/ +*.iml +rebel.* +.rebel.* + +# Idea +*.iml +*.ipr +*.iws +.idea + +target diff --git a/group24/1054283210/src/com/github/xiaozi123/coding2017/thirdWork/DownloadThread.java b/group24/1054283210/src/com/github/xiaozi123/coding2017/thirdWork/DownloadThread.java new file mode 100644 index 0000000000..c7da0ca056 --- /dev/null +++ b/group24/1054283210/src/com/github/xiaozi123/coding2017/thirdWork/DownloadThread.java @@ -0,0 +1,44 @@ +package com.github.xiaozi123.coding2017.thirdWork; + +import java.io.IOException; + +import com.github.xiaozi123.coding2017.thirdWork.api.Connection; + + +import java.io.RandomAccessFile; +import java.util.concurrent.CyclicBarrier; + + + +public class DownloadThread extends Thread{ + + Connection conn; + int startPos; + int endPos; + CyclicBarrier barrier; + String localFile; + public DownloadThread(Connection conn, int startPos, int endPos,String localFile,CyclicBarrier barrier){ + this.conn = conn; + this.startPos = startPos; + this.endPos = endPos; + this.localFile = localFile; + this.barrier = barrier; + } + public void run(){ + try { + System.out.println("Begin to read [" + startPos + "-" + endPos + "]"); + byte [] data = conn.read(startPos, endPos); + System.out.println("创建一个随机读取文件的对象"); + RandomAccessFile file = new RandomAccessFile(localFile,"rw"); + file.seek(startPos); + System.out.println("要写数据了"); + file.write(data); + file.close(); + conn.close(); + System.out.println(this.currentThread().getName()+"once over"); + barrier.await(); + } catch (Exception e) { + // TODO: handle exception + } + } +} diff --git a/group24/1054283210/src/com/github/xiaozi123/coding2017/thirdWork/FileDownloader.java b/group24/1054283210/src/com/github/xiaozi123/coding2017/thirdWork/FileDownloader.java new file mode 100644 index 0000000000..1084c9aaac --- /dev/null +++ b/group24/1054283210/src/com/github/xiaozi123/coding2017/thirdWork/FileDownloader.java @@ -0,0 +1,117 @@ +package com.github.xiaozi123.coding2017.thirdWork; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.concurrent.CyclicBarrier; + +import com.github.xiaozi123.coding2017.thirdWork.api.Connection; +import com.github.xiaozi123.coding2017.thirdWork.api.ConnectionException; +import com.github.xiaozi123.coding2017.thirdWork.api.ConnectionManager; +import com.github.xiaozi123.coding2017.thirdWork.api.DownloadListener; + +public class FileDownloader { + private String url; + private String localFile; + DownloadListener listener; + ConnectionManager cm; + + private static final int DOWNLOAD_THREAD_NUM = 3; + public FileDownloader(String _url){ + this.url = _url; +// this.localFile = localFile; + } + + 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 方法 + + // 下面的代码是实例代码,也就是说只有一个线程,你需要改造成多线程的 + CyclicBarrier barrier = new CyclicBarrier(DOWNLOAD_THREAD_NUM,new Runnable() {// 当所有的Thread都调用 await方法时,会执行后面的 barrierAction,调用后面这个线程 + @Override + public void run() { + listener.notifyFinished(); + } + }); + + Connection conn = null; + try { + conn = cm.open(this.url); + int length = conn.getContentLength();// 拿到将要下载文件的长度 + createPlaceHolderFile(this.localFile,length);//占位 + System.out.println("占位完毕"); + int [][] ranges = allocateDownloadRange(DOWNLOAD_THREAD_NUM,length);// 给每个线程分配开始位置和结束位置 + // 开始下载文件 + System.out.println("开始下载文件"); + for(int i = 0; i < DOWNLOAD_THREAD_NUM; i++){ + DownloadThread thread = new DownloadThread( + cm.open(url), + ranges[i][0], + ranges[i][1], + localFile, + barrier); + thread.start(); + System.out.println("第" + (i+1) + "个线程已经启动"); + } + + } catch (Exception e) { + e.printStackTrace(); + }finally{ + System.out.println("即将关闭连接"); + if(conn != null){ + conn.close(); + System.out.println("关闭连接成功"); + } + } + } + + public void setListener(DownloadListener listener){ + this.listener = listener; + } + public void setConnectionManager(ConnectionManager ucm){ + this.cm = ucm; + } + public DownloadListener getListener(){ + return this.listener; + } + private void createPlaceHolderFile(String fileName,int contentLen) throws IOException{ + RandomAccessFile file = new RandomAccessFile(fileName,"rw"); + for(int i = 0; i < contentLen; i++){ + file.write(0); + } + file.close(); + } + /** + * 给出线程数和文件长度,返回一个二维数组,里面存的是每个线程下载的开始位置和结束位置 + * @param threadNum + * @param contentLen + * @return + */ + private int [][] allocateDownloadRange(int threadNum, int contentLen){ + int [][] ranges = new int[threadNum][2];// 用二维数组存下每个线程的开始位置和结束位置 + + int eachThreadSize = contentLen / threadNum;// 每个线程需要下载的文件大小 + int left = contentLen % threadNum;// 剩下的归最后一个线程来处理 + + for(int i = 0; i totalLen){ + byte[] data = baos.toByteArray(); + return Arrays.copyOf(data, totalLen); + } + return baos.toByteArray(); + } + + @Override + public int getContentLength() { + URLConnection con; + try { + con = url.openConnection(); + return con.getContentLength(); + } catch (Exception e) { + e.printStackTrace(); + } + return -1; + } + + @Override + public void close() { + + } + +} diff --git a/group24/1054283210/src/com/github/xiaozi123/coding2017/thirdWork/impl/ConnectionManagerImpl.java b/group24/1054283210/src/com/github/xiaozi123/coding2017/thirdWork/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..edc92dfbf7 --- /dev/null +++ b/group24/1054283210/src/com/github/xiaozi123/coding2017/thirdWork/impl/ConnectionManagerImpl.java @@ -0,0 +1,17 @@ +package com.github.xiaozi123.coding2017.thirdWork.impl; + +import java.net.MalformedURLException; +import java.net.URL; + +import com.github.xiaozi123.coding2017.thirdWork.api.Connection; +import com.github.xiaozi123.coding2017.thirdWork.api.ConnectionException; +import com.github.xiaozi123.coding2017.thirdWork.api.ConnectionManager; + +public class ConnectionManagerImpl implements ConnectionManager { + + @Override + public Connection open(String url) throws ConnectionException { + return new ConnectionImpl(url); + } + +} diff --git "a/group24/1054283210/src/com/github/xiaozi123/coding2017/thirdWork/\346\226\207\347\253\240\345\234\260\345\235\200.txt" "b/group24/1054283210/src/com/github/xiaozi123/coding2017/thirdWork/\346\226\207\347\253\240\345\234\260\345\235\200.txt" new file mode 100644 index 0000000000..5c09311e90 --- /dev/null +++ "b/group24/1054283210/src/com/github/xiaozi123/coding2017/thirdWork/\346\226\207\347\253\240\345\234\260\345\235\200.txt" @@ -0,0 +1 @@ +http://www.jianshu.com/p/e5a2cdc5d4e5 \ No newline at end of file