😊

プログラミング自主学習 DAY69 TreeSet/TreeMap/LIFO/FIFO/synchronized collection

2023/08/04に公開

TreeSet

Setインターフェースの検索機能を強化したクラスだ。
HashSetとの違いはSort機能があり、ランダムではなく、順番で値を得ることができることだ。

https://o7planning.org/13605/java-treeset

TreeSet<E> treeSet = new TreeSet<>();

Setインターフェース変数でアップキャストすることもできるが、TreeSetの独自のメッソドがあるため、最初からTreeSetの変数を宣言してから、インスタンス化する場合が多い。

TreeSetExample

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の変数を宣言してから、インスタンス化する場合が多い。

TreeMapExample

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にオブジェクトを保存することができない。

ComparableExample

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というクラスを具象するこどで、整列を目指してみる。

Fruit
public class Fruit {
	public String name;
	public int price;
	
	public Fruit(String name, int price) {
		this.name = name;
		this.price = price;
	}
}
FruitComparator
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;
   }
}

ComparatorExample
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を具象したクラスだ。

Message
public class Message {
   public String command;
   public String to;
   
   public Message(String command, String to) {
	   this.command = command;
	   this.to = to;
   }
}

QueueExample
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