Created
April 11, 2020 23:53
-
-
Save Shtaba09/befef3166278c96925d13c3282972bc4 to your computer and use it in GitHub Desktop.
Shortner Зделать еще JDBC
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.javarush.task.task33.task3310; | |
public class ExceptionHandler { | |
public static void log(Exception e){ | |
System.out.println(e.getLocalizedMessage()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.javarush.task.task33.task3310; | |
import java.math.BigInteger; | |
import java.security.SecureRandom; | |
public class Helper { | |
public static String generateRandomString() { | |
return new BigInteger(130, new SecureRandom()).toString(36); | |
} | |
public static void printMessage(String message){ | |
System.out.println(message); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.javarush.task.task33.task3310; | |
import com.javarush.task.task33.task3310.strategy.StorageStrategy; | |
public class Shortener { | |
private Long lastId=0L; | |
private StorageStrategy storageStrategy; | |
public Shortener(StorageStrategy storageStrategy) { | |
this.storageStrategy = storageStrategy; | |
} | |
public synchronized Long getId(String string){ | |
if (storageStrategy.containsValue(string)){ | |
return storageStrategy.getKey(string); | |
}else { | |
lastId++; | |
storageStrategy.put(lastId,string); | |
return lastId; | |
} | |
} | |
public synchronized String getString(Long id){ | |
return storageStrategy.getValue(id); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.javarush.task.task33.task3310; | |
import com.javarush.task.task33.task3310.strategy.*; | |
import java.util.Date; | |
import java.util.HashSet; | |
import java.util.Set; | |
public class Solution { | |
public static void main(String[] args){ | |
HashMapStorageStrategy strategy = new HashMapStorageStrategy(); | |
OurHashMapStorageStrategy strategy1 = new OurHashMapStorageStrategy(); | |
FileStorageStrategy strategy2 = new FileStorageStrategy(); | |
OurHashBiMapStorageStrategy strategy3 = new OurHashBiMapStorageStrategy(); | |
HashBiMapStorageStrategy strategy4 = new HashBiMapStorageStrategy(); | |
DualHashBidiMapStorageStrategy strategy5 = new DualHashBidiMapStorageStrategy(); | |
testStrategy(strategy,10000L); | |
testStrategy(strategy1,10000L); | |
// testStrategy(strategy2,2000L); | |
testStrategy(strategy3,10000L); | |
testStrategy(strategy4,10000L); | |
testStrategy(strategy5,10000L); | |
} | |
public static Set<Long> getIds(Shortener shortener, Set<String> strings){ | |
Set<Long> ids = new HashSet<>(); | |
for(String str : strings){ | |
ids.add(shortener.getId(str)); | |
} | |
return ids; | |
} | |
public static Set<String> getStrings(Shortener shortener, Set<Long> keys){ | |
Set<String> strings = new HashSet<>(); | |
for(Long key : keys){ | |
strings.add(shortener.getString(key)); | |
} | |
return strings; | |
} | |
public static void testStrategy(StorageStrategy strategy, long elementsNumber){ | |
Helper.printMessage(strategy.getClass().getSimpleName()); | |
Set<String> strings = new HashSet<>(); | |
for(long i = 0L; i<elementsNumber; i++){ | |
strings.add(Helper.generateRandomString()); | |
} | |
Shortener shortener= new Shortener(strategy); | |
Date start = new Date(); | |
Set<Long> ids = getIds(shortener,strings); | |
Date stop = new Date(); | |
Long time = stop.getTime()-start.getTime(); | |
Helper.printMessage(time.toString()); | |
start = new Date(); | |
Set<String> strings1 = getStrings(shortener,ids); | |
stop = new Date(); | |
time = stop.getTime()-start.getTime(); | |
Helper.printMessage(time.toString()); | |
if(strings.containsAll(strings1)){ | |
Helper.printMessage("Тест пройден."); | |
} else { Helper.printMessage("Тест не пройден.");} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.javarush.task.task33.task3310.strategy; | |
import org.apache.commons.collections4.BidiMap; | |
import org.apache.commons.collections4.bidimap.DualHashBidiMap; | |
public class DualHashBidiMapStorageStrategy implements StorageStrategy { | |
private DualHashBidiMap data = new DualHashBidiMap(); | |
@Override | |
public boolean containsKey(Long key) { | |
return data.containsKey(key); | |
} | |
@Override | |
public boolean containsValue(String value) { | |
return data.containsValue(value); | |
} | |
@Override | |
public void put(Long key, String value) { | |
data.put(key,value); | |
} | |
@Override | |
public Long getKey(String value) { | |
return (Long) data.getKey(value); | |
} | |
@Override | |
public String getValue(Long key) { | |
return (String) data.get(key); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.javarush.task.task33.task3310.strategy; | |
import java.io.Serializable; | |
import java.util.Objects; | |
public class Entry implements Serializable { | |
Long key; | |
String value; | |
Entry next; | |
int hash; | |
public Entry(int hash, Long key, String value, Entry next) { | |
this.key = key; | |
this.value = value; | |
this.next = next; | |
this.hash = hash; | |
} | |
public Long getKey(){ | |
return key; | |
} | |
public String getValue(){ | |
return value; | |
} | |
@Override | |
public boolean equals(Object o) { | |
if (this == o) return true; | |
if (o == null || getClass() != o.getClass()) return false; | |
Entry entry = (Entry) o; | |
return Objects.equals(key, entry.key) && | |
Objects.equals(value, entry.value); | |
} | |
@Override | |
public int hashCode() { | |
return Objects.hash(key, value); | |
} | |
@Override | |
public String toString() { | |
return key+"="+value; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.javarush.task.task33.task3310.strategy; | |
import com.fasterxml.jackson.databind.ObjectWriter; | |
import java.io.*; | |
import java.nio.file.Files; | |
import java.nio.file.Path; | |
public class FileBucket { | |
Path path ; | |
public FileBucket() { | |
try { | |
path= Files.createTempFile(null,null); | |
Files.deleteIfExists(path); | |
Files.createFile(path); | |
path.toFile().deleteOnExit(); | |
} catch (IOException e) { | |
//ignored | |
} | |
} | |
public long getFileSize() { | |
try { | |
return Files.size(path); | |
} catch (IOException e) { | |
return 0L; | |
} | |
} | |
public void putEntry(Entry entry){ | |
try { | |
ObjectOutputStream objectWriter = new ObjectOutputStream(Files.newOutputStream(path)); | |
objectWriter.writeObject(entry); | |
objectWriter.flush(); | |
objectWriter.close(); | |
} catch (IOException e) { | |
//ign | |
} | |
} | |
public Entry getEntry(){ | |
if(getFileSize()==0L)return null; | |
try { | |
ObjectInputStream objectReader = new ObjectInputStream(Files.newInputStream(path)); | |
Entry entry= (Entry)objectReader.readObject(); | |
objectReader.close(); | |
return entry; | |
} catch (IOException | ClassNotFoundException e) { } | |
return null; | |
} | |
public void remove(){ | |
try { | |
Files.delete(path); | |
} catch (IOException e) { | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.javarush.task.task33.task3310.strategy; | |
public class FileStorageStrategy implements StorageStrategy{ | |
static final int DEFAULT_INITIAL_CAPACITY = 16; | |
static final long DEFAULT_BUCKET_SIZE_LIMIT = 10000L; | |
FileBucket[] table = new FileBucket[DEFAULT_INITIAL_CAPACITY]; | |
private long bucketSizeLimit = DEFAULT_BUCKET_SIZE_LIMIT; | |
long maxBucketSize; | |
int size; | |
public long getBucketSizeLimit() { | |
return bucketSizeLimit; | |
} | |
public void setBucketSizeLimit(long bucketSizeLimit) { | |
this.bucketSizeLimit = bucketSizeLimit; | |
} | |
public int hash(Long k){ | |
int h=Integer.parseInt(k.toString()); | |
h ^= (h >>> 20) ^ (h >>> 12); | |
return h ^ (h >>> 7) ^ (h >>> 4); | |
} | |
public int indexFor(int hash, int length){ | |
return hash & (length - 1); | |
} | |
public Entry getEntry(Long key){ | |
int hash = (key == null) ? 0 : hash(key); | |
for (Entry e = table[indexFor(hash, table.length)].getEntry(); | |
e != null; | |
e = e.next) { | |
Long k; | |
if (e.hash == hash && ((k = e.key).equals(key) || (key != null && key.equals(k)))) | |
return e; | |
} | |
return null; | |
} | |
public FileStorageStrategy() { | |
table = new FileBucket[DEFAULT_INITIAL_CAPACITY]; | |
for(int i = 0; i < table.length; ++i) | |
table[i] = new FileBucket(); | |
} | |
public void resize(int newCapacity){ | |
FileBucket[] newTable = new FileBucket[newCapacity]; | |
for (FileBucket fileBucket : newTable) | |
fileBucket = new FileBucket(); | |
transfer(newTable); | |
table = newTable; | |
} | |
public void transfer(FileBucket[] newTable) { | |
int newCapacity = newTable.length; | |
for (int i = 0; i < table.length; i++) { | |
if (table[i] == null) continue; | |
Entry entry = table[i].getEntry(); | |
while (entry != null) { | |
Entry next = entry.next; | |
int indexFor = indexFor(entry.hash, newCapacity); | |
entry.next = newTable[indexFor].getEntry(); | |
newTable[indexFor].putEntry(entry); | |
entry = next; | |
} | |
table[i].remove(); | |
table[i] = null; | |
} | |
} | |
public void addEntry(int hash, Long key, String value, int bucketIndex) { | |
Entry entry = table[bucketIndex].getEntry(); | |
table[bucketIndex].putEntry(new Entry(hash, key, value, entry)); | |
size++; | |
if(table[bucketIndex].getFileSize() > bucketSizeLimit) { | |
resize(2 * table.length); } | |
} | |
public void createEntry(int hash, Long key, String value, int bucketIndex) { | |
table[bucketIndex] = new FileBucket(); | |
table[bucketIndex].putEntry(new Entry(hash, key, value, null)); | |
size++; | |
} | |
@Override | |
public boolean containsKey(Long key) { | |
return getEntry(key) != null; | |
} | |
@Override | |
public boolean containsValue(String value) { | |
if (value == null){return false;} | |
for (int i = 0; i < table.length ; i++) | |
if (table[i] != null) { | |
for (Entry e = table[i].getEntry(); e != null ; e = e.next) | |
if (value.equals(e.value)) | |
return true;} | |
return false; | |
} | |
@Override | |
public void put(Long key, String value) { | |
int hash = hash(key); | |
int i = indexFor(hash, table.length); | |
if (table[i] == null) | |
createEntry(hash, key, value, i); | |
else { | |
for (Entry entry = table[i].getEntry(); entry != null; entry = entry.next) { | |
Long k; | |
if (entry.hash == hash && ((k = entry.key) == key || key.equals(k))) | |
entry.value = value; | |
} | |
addEntry(hash, key, value, i); | |
} | |
} | |
@Override | |
public Long getKey(String value) { | |
for (int i = 0; i < table.length ; i++) { | |
if (table[i] == null) continue; | |
for (Entry e = table[i].getEntry(); e != null; e = e.next) | |
if (value.equals(e.value)) | |
return e.key; | |
} | |
return null; | |
} | |
@Override | |
public String getValue(Long key) { | |
return getEntry(key).getValue(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.javarush.task.task33.task3310.strategy; | |
import com.google.common.collect.BiMap; | |
import com.google.common.collect.HashBiMap; | |
public class HashBiMapStorageStrategy implements StorageStrategy { | |
private HashBiMap data = HashBiMap.create() ; | |
@Override | |
public boolean containsKey(Long key) { | |
return data.containsKey(key); | |
} | |
@Override | |
public boolean containsValue(String value) { | |
return data.containsValue(value); | |
} | |
@Override | |
public void put(Long key, String value) { | |
data.put(key,value); | |
} | |
@Override | |
public Long getKey(String value) { | |
BiMap copy = data.inverse(); | |
return (Long) copy.get(value); | |
} | |
@Override | |
public String getValue(Long key) { | |
return (String) data.get(key); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.javarush.task.task33.task3310.strategy; | |
import java.util.HashMap; | |
import java.util.Map; | |
public class HashMapStorageStrategy implements StorageStrategy { | |
private HashMap<Long, String> data = new HashMap<>(); | |
@Override | |
public boolean containsKey(Long key) { | |
return data.containsKey(key); | |
} | |
@Override | |
public boolean containsValue(String value) { | |
return data.containsValue(value); | |
} | |
@Override | |
public void put(Long key, String value) { | |
data.put(key,value); | |
} | |
@Override | |
public Long getKey(String value) { | |
for (Map.Entry<Long,String> pair : data.entrySet()){ | |
if(value.contains(pair.getValue())){ | |
return pair.getKey(); | |
} | |
} | |
return null; | |
} | |
@Override | |
public String getValue(Long key) { | |
return data.get(key); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.javarush.task.task33.task3310.strategy; | |
import java.util.HashMap; | |
public class OurHashBiMapStorageStrategy implements StorageStrategy { | |
private HashMap<Long, String> k2v = new HashMap<>(); | |
private HashMap<String, Long> v2k = new HashMap<>(); | |
@Override | |
public boolean containsKey(Long key) { | |
return k2v.containsKey(key); | |
} | |
@Override | |
public boolean containsValue(String value) { | |
return v2k.containsKey(value); | |
} | |
@Override | |
public void put(Long key, String value) { | |
k2v.put(key,value); | |
v2k.put(value,key); | |
} | |
@Override | |
public Long getKey(String value) { | |
return v2k.get(value); | |
} | |
@Override | |
public String getValue(Long key) { | |
return k2v.get(key); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.javarush.task.task33.task3310.strategy; | |
public class OurHashMapStorageStrategy implements StorageStrategy { | |
static final int DEFAULT_INITIAL_CAPACITY = 16; | |
static final float DEFAULT_LOAD_FACTOR = 0.75f; | |
Entry[] table = new Entry[DEFAULT_INITIAL_CAPACITY]; | |
int size; | |
int threshold = (int) (DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR); | |
float loadFactor = DEFAULT_LOAD_FACTOR; | |
public int hash(Long k){ | |
int h=Integer.parseInt(k.toString()); | |
h ^= (h >>> 20) ^ (h >>> 12); | |
return h ^ (h >>> 7) ^ (h >>> 4); | |
} | |
public int indexFor(int hash, int length){ | |
return hash & (length - 1); | |
} | |
public Entry getEntry(Long key){ | |
int hash = (key == null) ? 0 : hash(key); | |
for (Entry e = table[indexFor(hash, table.length)]; | |
e != null; | |
e = e.next) { | |
Object k; | |
if (e.hash == hash && | |
((k = e.key) == key || (key != null && key.equals(k)))) | |
return e; | |
} | |
return null; | |
} | |
public void resize(int newCapacity){ | |
Entry[] newTable = new Entry[newCapacity]; | |
transfer(newTable); | |
table = newTable; | |
threshold = (int)(newCapacity * loadFactor); | |
} | |
public void transfer(Entry[] newTable) { | |
Entry[] src = table; | |
int newCapacity = newTable.length; | |
for (int j = 0; j < src.length; j++) { | |
Entry e = src[j]; | |
if (e != null) { | |
src[j] = null; | |
do { | |
Entry next = e.next; | |
int i = indexFor(e.hash, newCapacity); | |
e.next = newTable[i]; | |
newTable[i] = e; | |
e = next; | |
} while (e != null); | |
} | |
} | |
} | |
public void addEntry(int hash, Long key, String value, int bucketIndex){ | |
Entry e = table[bucketIndex]; | |
table[bucketIndex] = new Entry(hash, key, value, e); | |
if (size++ >= threshold) | |
resize(2 * table.length); | |
} | |
public void createEntry(int hash, Long key, String value, int bucketIndex){ | |
Entry e = table[bucketIndex]; | |
table[bucketIndex] = new Entry(hash, key, value, e); | |
size++; | |
} | |
@Override | |
public boolean containsKey(Long key) { | |
for(Entry entry : table){ | |
if (entry.getKey().equals(key)){return true;} | |
} | |
return false; | |
} | |
@Override | |
public boolean containsValue(String value) { | |
if (value == null){return false;} | |
Entry[] tab = table; | |
for (int i = 0; i < tab.length ; i++) | |
for (Entry e = tab[i] ; e != null ; e = e.next) | |
if (value.equals(e.value)) | |
return true; | |
return false; | |
} | |
@Override | |
public void put(Long key, String value) { | |
int hash = hash(key); | |
createEntry(hash,key,value,indexFor(hash,table.length)); | |
} | |
@Override | |
public Long getKey(String value) { | |
for(Entry entry : table){ | |
if(entry!=null) { | |
if (entry.value.equals(value)) { | |
return entry.getKey(); | |
} | |
} | |
} | |
return null; | |
} | |
@Override | |
public String getValue(Long key) { | |
Entry[] tab = table; | |
for (int i = 0; i < tab.length ; i++) | |
for (Entry e = tab[i] ; e != null ; e = e.next) | |
if (key.equals(e.key)) | |
return e.getValue(); | |
return null; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.javarush.task.task33.task3310.strategy; | |
public interface StorageStrategy { | |
public boolean containsKey(Long key); | |
public boolean containsValue(String value); | |
public void put(Long key, String value); | |
public Long getKey(String value); | |
public String getValue(Long key); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.javarush.task.task33.task3310.tests; | |
import com.javarush.task.task33.task3310.Shortener; | |
import com.javarush.task.task33.task3310.strategy.*; | |
import org.junit.Assert; | |
import org.junit.Test; | |
public class FunctionalTest { | |
public void testStorage(Shortener shortener){ | |
String one = "TestThis"; | |
String two = "NotThis"; | |
String three = "TestThis"; | |
Long idOne = shortener.getId(one); | |
Long idTwo = shortener.getId(two); | |
Long idThree = shortener.getId(three); | |
Assert.assertNotEquals("idTwo equalsh 1",idTwo,idOne); | |
Assert.assertNotEquals("idTwo equalsh 3",idTwo,idThree); | |
Assert.assertEquals("id1 not equals id3 ",idOne,idThree); | |
String oneTest =shortener.getString(idOne); | |
String twoTest = shortener.getString(idTwo); | |
String threeTest= shortener.getString(idThree); | |
Assert.assertEquals("String one fail",one,oneTest); | |
Assert.assertEquals("String two fail",two,twoTest); | |
Assert.assertEquals("String three fail",three,threeTest); | |
} | |
@Test | |
public void testHashMapStorageStrategy(){ | |
Shortener shortener = new Shortener(new HashMapStorageStrategy()); | |
testStorage(shortener); | |
} | |
@Test | |
public void testOurHashMapStorageStrategy(){ | |
Shortener shortener = new Shortener(new OurHashMapStorageStrategy()); | |
testStorage(shortener); | |
} | |
@Test | |
public void testFileStorageStrategy(){ | |
Shortener shortener = new Shortener(new FileStorageStrategy()); | |
testStorage(shortener); | |
} | |
@Test | |
public void testHashBiMapStorageStrategy(){ | |
Shortener shortener = new Shortener(new HashBiMapStorageStrategy()); | |
testStorage(shortener); | |
} | |
@Test | |
public void testDualHashBidiMapStorageStrategy(){ | |
Shortener shortener = new Shortener(new DualHashBidiMapStorageStrategy()); | |
testStorage(shortener); | |
} | |
@Test | |
public void testOurHashBiMapStorageStrategy(){ | |
Shortener shortener = new Shortener(new OurHashBiMapStorageStrategy()); | |
testStorage(shortener); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.javarush.task.task33.task3310.tests; | |
import com.javarush.task.task33.task3310.Helper; | |
import com.javarush.task.task33.task3310.Shortener; | |
import com.javarush.task.task33.task3310.strategy.HashBiMapStorageStrategy; | |
import com.javarush.task.task33.task3310.strategy.HashMapStorageStrategy; | |
import org.junit.Assert; | |
import org.junit.Test; | |
import java.util.Date; | |
import java.util.HashSet; | |
import java.util.Set; | |
public class SpeedTest { | |
public long getTimeToGetIds(Shortener shortener, Set<String> strings, Set<Long> ids){ | |
Date start = new Date(); | |
for(String str :strings){ | |
ids.add(shortener.getId(str)); | |
} | |
Date stop = new Date(); | |
return stop.getTime()-start.getTime(); | |
} | |
public long getTimeToGetStrings(Shortener shortener, Set<Long> ids, Set<String> strings){ | |
Date start = new Date(); | |
for(Long id :ids){ | |
strings.add(shortener.getString(id)); | |
} | |
Date stop = new Date(); | |
return stop.getTime()-start.getTime(); | |
} | |
@Test | |
public void testHashMapStorage(){ | |
Shortener shortener1 = new Shortener(new HashMapStorageStrategy()); | |
Shortener shortener2 = new Shortener(new HashBiMapStorageStrategy()); | |
Set<String> origStrings = new HashSet<>(); | |
Set<Long> ids1 = new HashSet<>(); | |
Set<Long> ids2 = new HashSet<>(); | |
for (int i=0;i<10000; i++){ | |
origStrings.add(Helper.generateRandomString()); | |
} | |
Long time1 = getTimeToGetIds(shortener1,origStrings,ids1); | |
Long time2 = getTimeToGetIds(shortener2,origStrings,ids2); | |
Assert.assertTrue((time1>time2)); | |
time1 = getTimeToGetStrings(shortener1,ids1,new HashSet<>()); | |
time2 = getTimeToGetStrings(shortener2,ids2,new HashSet<>()); | |
Assert.assertEquals(time1,time2,30); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
taskKey="com.javarush.task.task33.task3310.big16"\n\nShortener (16) | |
Что можешь сделать самостоятельно (тестов на этот пункт нет): | |
- Добавить стратегию, основанную на работе с базой данных. Гугли JDBC. | |
- Сделать веб сервис, который будет для любого url или строки возвращать | |
идентификатор, а для идентификатора строку. | |
- Написать вариант HashMap с использованием двух потоков, где один поток будет | |
отвечать за работу с элементами, а второй следить за количеством элементов. Когда | |
количество элементов превысит порог threshold, второй поток должен увеличить | |
размер table в 2 раза. При этом, первый поток ничего не должен знать о пороге. | |
Твои достижения: | |
- Повторил паттерн Стратегия. | |
- Получил опыт работы с библиотекой Guava. | |
- Получил опыт работы с Apache Commons Collections. | |
- Попробовал писать тесты, используя Junit. | |
- Еще на шаг продвинулся к работе Java программистом. | |
Поздравляю! Я горжусь тобой! | |
Ты отличный ученик! | |
Требования: | |
1. Shortener готов! | |
Shortener (15) | |
Напишем еще один тест, который проверит, что получить идентификатор для строки | |
используя стратегию HashBiMapStorageStrategy можно быстрее, чем используя | |
стратегию HashMapStorageStrategy. | |
15.1. Создай класс SpeedTest в пакете tests. | |
15.2. Добавь в класс метод long getTimeToGetIds(Shortener shortener, Set<String> | |
strings, Set<Long> ids). Он должен возвращать время в миллисекундах необходимое | |
для получения идентификаторов для всех строк из strings. Идентификаторы | |
должны быть записаны в ids. | |
15.3. Добавь в класс метод long getTimeToGetStrings(Shortener shortener, | |
Set<Long> ids, Set<String> strings). Он должен возвращать время в миллисекундах | |
необходимое для получения строк для всех идентификаторов из ids. Строки | |
должны быть записаны в strings. | |
15.4. Добавь в класс SpeedTest тест testHashMapStorage(). Он должен: | |
15.4.1. Создавать два объекта типа Shortener, один на базе | |
HashMapStorageStrategy, второй на базе HashBiMapStorageStrategy. Назовем | |
их shortener1 и shortener2. | |
15.4.2. Генерировать с помощью Helper 10000 строк и помещать их в сет со | |
строками, назовем его origStrings. | |
15.4.3. Получать время получения идентификаторов для origStrings (вызывать | |
метод getTimeToGetIds для shortener1, а затем для shortener2). | |
15.4.4. Проверять с помощью junit, что время, полученное в предыдущем пункте | |
для shortener1 больше, чем для shortener2. | |
15.4.5. Получать время получения строк (вызывать метод getTimeToGetStrings | |
для shortener1 и shortener2). | |
15.4.6. Проверять с помощью junit, что время, полученное в предыдущем пункте | |
для shortener1 примерно равно времени для shortener2. Используй метод | |
assertEquals(float expected, float actual, float delta). В качестве delta можно | |
использовать 30, этого вполне достаточно для наших экспериментов. | |
Shortener (14) | |
Мы много раз тестировали наши стратегии с помощью метода testStrategy() класса | |
Solution. Пришло время написать настоящие юнит тесты с использованием junit. | |
14.1. Прочитай что такое юнит тесты. | |
14.2. Скачай и подключи библиотеку Junit 4.12. Разберись как ей пользоваться. | |
Библиотека Junit зависит от библиотеки hamcrest-core. Подключи и ее. Используй версию 1.3. | |
14.3. Добавь класс FunctionalTest в пакет tests. В этом классе мы проверим | |
функциональность наших стратегий. | |
14.4. Добавь в класс FunctionalTest метод testStorage(Shortener shortener). Он | |
должен: | |
14.4.1. Создавать три строки. Текст 1 и 3 строк должен быть одинаковым. | |
14.4.2. Получать и сохранять идентификаторы для всех трех строк с помощью | |
shortener. | |
14.4.3. Проверять, что идентификатор для 2 строки не равен идентификатору для 1 | |
и 3 строк. Подсказка: метод Assert.assertNotEquals. | |
14.4.4. Проверять, что идентификаторы для 1 и 3 строк равны. Подсказка: метод | |
Assert.assertEquals. | |
14.4.5. Получать три строки по трем идентификаторам с помощью shortener. | |
14.4.6. Проверять, что строки, полученные в предыдущем пункте, эквивалентны | |
оригинальным. Подсказка: метод Assert.assertEquals. | |
14.5. Добавь в класс FunctionalTest тесты: | |
14.5.1. testHashMapStorageStrategy() | |
14.5.2. testOurHashMapStorageStrategy() | |
14.5.3. testFileStorageStrategy() | |
14.5.4. testHashBiMapStorageStrategy() | |
14.5.5. testDualHashBidiMapStorageStrategy() | |
14.5.6. testOurHashBiMapStorageStrategy() | |
Каждый тест должен иметь аннотацию @Test, создавать подходящую стратегию, | |
создавать объект класса Shortener на базе этой стратегии и вызывать метод | |
testStorage для него. | |
Запусти и проверь, что все тесты проходят. | |
Shortener (13) | |
Рассмотрим еще одну реализацию BiMap, на этот раз из Apache Commons Collections. | |
13.1. Скачай и подключи Apache Commons Collections 4.0. | |
13.2. Реализуй стратегию DualHashBidiMapStorageStrategy. Она должна: | |
13.2.1. Поддерживать интерфейс StorageStrategy. | |
13.2.2. Внутри иметь только одно поле data с типом DualHashBidiMap. | |
13.3. Проверь новую стратегию в методе main(). Запусти программу и сравни | |
скорость работы шести стратегий. | |
Shortener (12) | |
Задача, когда требуется создать Map, работающий в две стороны (по ключу получать | |
значение, а по значению ключ) не такая уж и редкая. Такие коллекции уже | |
реализованы в различных сторонних библиотеках коллекций. Одна из таких Guava от | |
Google. | |
12.1. Скачай и подключи библиотеку guava версии 19.0. | |
12.2. Реализуй стратегию HashBiMapStorageStrategy. Она должна: | |
12.2.1. Поддерживать интерфейс StorageStrategy. | |
12.2.2. Внутри иметь только одно поле data типа HashBiMap. | |
12.3. Проверь новую стратегию в методе main(). Запусти программу и сравни | |
скорость работы пяти стратегий. | |
Shortener (11) | |
Как ты заметил, получение идентификатора для строки требует намного больше | |
времени, чем получение строки по идентификатору. Это ожидаемо и следует из | |
реализации HashMap. Давай напишем четвертую стратегию | |
OurHashBiMapStorageStrategy, которая будет лишена этого недостатка. | |
11.1. Создай класс OurHashBiMapStorageStrategy, реализующий интерфейс | |
StorageStrategy. | |
11.2. Добавь в него два поля HashMap<Long, String> k2v и HashMap<String, Long> v2k. | |
Первое будет хранить соответствие ключа и значения, а второе наоборот: значения | |
и ключа. | |
11.3. Реализуй методы интерфейса StorageStrategy, обеспечив максимальную | |
скорость. Подсказка: при добавлении новой пары ключ-значение необходимо | |
добавлять ее сразу в два поля. | |
Проверь новую стратегию в методе main(). Запусти программу и сравни скорость работы | |
всех 4х стратегий. Убедись, что мы значительно увеличили скорость получения | |
идентификатора. Но как ты понимаешь, у этого решения есть не только плюсы, но и минусы. | |
Подумай в каких случаях имеет смысл использовать OurHashBiMapStorageStrategy, а в каких | |
HashMapStorageStrategy. | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment