プログラミング自主学習 DAY69 TreeSet/TreeMap/LIFO/FIFO/synchronized collection
TreeSet
Setインターフェースの検索機能を強化したクラスだ。
HashSetとの違いはSort機能があり、ランダムではなく、順番で値を得ることができることだ。
https://o7planning.org/13605/java-treeset
TreeSet<E> treeSet = new TreeSet<>();
Setインターフェース変数でアップキャストすることもできるが、TreeSetの独自のメッソドがあるため、最初からTreeSetの変数を宣言してから、インスタンス化する場合が多い。
import java.util.NavigableSet;
import java.util.TreeSet;
public class TreeSetExample {
public static void main(String[] args) {
TreeSet<Integer> scores = new TreeSet<>();
scores.add(87);
scores.add(98);
scores.add(75);
scores.add(95);
scores.add(80);
for(Integer s : scores) {
System.out.print(s + " ");
}
System.out.println("\n");
System.out.println("lowest number : " + scores.first());
System.out.println("highest number : " + scores.last());
System.out.println("under 95(n<95) : " + scores.lower(95));
System.out.println("up 95(n>95): " + scores.higher(95));
System.out.println("under 95(n<=95) : " + scores.floor(95));
System.out.println("up 85(n>=85) : " + scores.ceiling(85));
System.out.println();
//Descending
NavigableSet<Integer> descendingScores = scores.descendingSet();
for(Integer s : descendingScores) {
System.out.print(s + " ");
}
System.out.println();
//Research
NavigableSet<Integer> rangeSet = scores.tailSet(80, true);
for(Integer s : rangeSet) {
System.out.print(s + " ");
}
System.out.println();
rangeSet = scores.subSet(80, true, 90, false);
for(Integer s : rangeSet) {
System.out.print(s + " ");
}
System.out.println();
}
}
75 80 87 95 98
lowest number : 75
highest number : 98
under 95(n<95) : 87
up 95(n>95): 98
under 95(n<=95) : 95
up 85(n>=85) : 87
98 95 87 80 75
80 87 95 98
80 87
TreeMap
TreeSetと同じく、整列されたHashMap。親ノードから左が小さい値、右が大きな値だ。
違いは、valueではなく、keyの値を整列する。
Mapインターフェース変数でアップキャストすることもできるが、TreeMapも独自のメッソドがあるため、最初からTreeSetの変数を宣言してから、インスタンス化する場合が多い。
public class TreeMapExample {
public static void main(String[] args) {
TreeMap<String, Integer> treeMap = new TreeMap<>();
treeMap.put("apple",10);
treeMap.put("forever",60);
treeMap.put("description",40);
treeMap.put("ever",50);
treeMap.put("zoo",80);
treeMap.put("base",20);
treeMap.put("guess",70);
treeMap.put("cherry",30);
//get all entries
Set<Entry<String,Integer>> entrySet = treeMap.entrySet();
for(Entry<String, Integer> entry : entrySet) {
System.out.println(entry.getKey() + "-" + entry.getValue());
}
System.out.println();
//get entry from key
Entry<String, Integer> entry = null;
entry = treeMap.firstEntry();
System.out.println("first word(deepest) :" + entry.getKey() + "-" + entry.getValue());
entry = treeMap.lastEntry();
System.out.println("last word(Highest) :" + entry.getKey() + "-" + entry.getValue());
entry = treeMap.lowerEntry("ever");
System.out.println("before word(previous) :" + entry.getKey() + "-" + entry.getValue());
entry = treeMap.higherEntry("ever");
System.out.println("after word(next) :" + entry.getKey() + "-" + entry.getValue());
System.out.println();
//Descending
NavigableMap<String, Integer> decendingMap = treeMap.descendingMap();
Set<Entry<String, Integer>> descendingEntrySet = decendingMap.entrySet();
for(Entry <String, Integer> e : descendingEntrySet) {
System.out.println(e.getKey() + "-" + e.getValue());
}
System.out.println();
System.out.println("Research between c & h");
NavigableMap<String, Integer> rangeMap = treeMap.subMap("c", true, "h", false);
for(Entry<String, Integer> e : rangeMap.entrySet()) {
System.out.println(e.getKey() + "-" + e.getValue());
}
}
}
apple-10
base-20
cherry-30
description-40
ever-50
forever-60
guess-70
zoo-80
first word(deepest) :apple-10
last word(Highest) :zoo-80
before word(previous) :description-40
after word(next) :forever-60
zoo-80
guess-70
forever-60
ever-50
description-40
cherry-30
base-20
apple-10
Research between c & h
cherry-30
description-40
ever-50
forever-60
guess-70
Comparable&Comparator
String, Double, Inetegerは、Comparabaleインタフェースを具象しているが、カスタムクラスは比較をしたい場合、かならず、Comparableを具象しなければ、ならない。
Comparableがないオブジェクトは、Mapにオブジェクトを保存することができない。
public class Person implements Comparable<Person>{
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Person o) {
if(age < o.age) return -1;
else if(age == o.age) return 0;
else return 1;
}
}
감자바 : 25
박지원 : 31
홍길동 : 45
二つ目の方法としては、コンストラクタのパラメータにComparatorを具象することでTreeに保存することもできる。
TreeSet<E> treeSet = new TreeSet<E>(new comparatorImpl());
TreeMap<E> treeMap = new TreeMap<K,V>(new comparatorImpl());
Fruitというクラスと、FruitComparatorというクラスを具象するこどで、整列を目指してみる。
public class Fruit {
public String name;
public int price;
public Fruit(String name, int price) {
this.name = name;
this.price = price;
}
}
import java.util.Comparator;
public class FruitComparator implements Comparator<Fruit>{
@Override
public int compare(Fruit o1, Fruit o2) {
if(o1.price < o2.price) return -1;
else if(o1.price == o2.price) return 0;
else return 1;
}
}
package ch15.sec05.exam04;
import java.util.TreeSet;
public class ComparatorExample {
public static void main(String[] args) {
TreeSet<Fruit> treeSet = new TreeSet<Fruit>(new FruitComparator());
treeSet.add(new Fruit("포도", 3000));
treeSet.add(new Fruit("수박", 10000));
treeSet.add(new Fruit("딸기", 6000));
for(Fruit fruit : treeSet) {
System.out.println(fruit.name + ":" + fruit.price);
}
}
}
LIFO(Stack)
データーを入れることをPush、出すことをpopだと表現する。
https://medium.com/@shawnnkoski/data-structures-stack-f34642489ac6
最後に入ったデーターが最初に出る。配列を270度回転した形と似ている。
Vectorをextendsしたため、マルチスレッドでも安全だ。
Stack<E> stack = new Stack<E>();
import java.util.Stack;
public class StackExample {
public static void main(String[] args) {
Stack<Coin> coinBox = new Stack<>();
coinBox.push(new Coin(100));
coinBox.push(new Coin(50));
coinBox.push(new Coin(500));
coinBox.push(new Coin(10));
while(!coinBox.isEmpty()) {
Coin coin = coinBox.pop();
System.out.println("pick up " + coin.getValue());
}
}
}
FIFO(queue)
データーを入れることをoffer、出すことをpollだと表現する。
Queueは、インタフェースであるため、具象したクラスが必修だ。
日常でよく見つけるアルゴリズムだ。病院に行って順番に入り、出ることと同じ流れだ。
Queue<E> queue = new LinkedList<E>();
LinkedListは、Queueを具象したクラスだ。
public class Message {
public String command;
public String to;
public Message(String command, String to) {
this.command = command;
this.to = to;
}
}
import java.util.Queue;
import java.util.LinkedList;
public class QueueExample {
public static void main(String[] args) {
Queue<Message> messageQueue = new LinkedList<>();
messageQueue.offer(new Message("SendMail", "jack"));
messageQueue.offer(new Message("SendSMS", "adam"));
messageQueue.offer(new Message("SendLine", "aya"));
while(!messageQueue.isEmpty()) {
Message message = messageQueue.poll();
switch(message.command) {
case "SendMail" :{
System.out.println(message.to + "님에게 메일을 보냅니다");
break;
}
case "SendSMS" : {
System.out.println(message.to + "님에게 SMS을 보냅니다");
break;
}
case "SendLine" :{
System.out.println(message.to + "님에게 카카오톡을 보냅니다");
break;
}
}
}
}
}
Synchoronized Collection
マルチスレッド環境で、ArrayListとHashMapなどはThread safeではない。しかし、場合によって、バルチスレッド環境でシングルスレッド環境のCollectionを使用する際もある。
その際には、非同期化されたメソッドを同期化するsynchoronized methodを活用する。
synchronizedList(List<T> list)
synchronizedMap(Map <K,V> m)
synchronizedSet(Set<T>s )
こちらにCollectionを具象したクラスのオブジェクトを入れると同期化したCollectionをリータンする。
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class SynchoronizedMapExample {
public static void main(String[] args) {
Map<Integer, String> map = Collections.synchronizedMap(new HashMap<>()) ;
Thread threadA = new Thread() {
@Override
public void run() {
for(int i=1; i<=1000; i++) {
map.put(i, "내용"+i);
}
}
};
Thread threadB = new Thread() {
@Override
public void run() {
for(int i=1001; i<=2000; i++) {
map.put(i, "내용"+i);
}
}
};
threadA.start();
threadB.start();
try {
threadA.join();
threadB.join();
} catch (Exception e) {
}
int size = map.size();
System.out.println("total object :" + size);
}
}
total object :2000
マルチスレッド環境で、1000個ずつ、entryを生成した結果、2000個が無事にMapに入ったことが分かる。
Discussion