30 Kasım 2019 Cumartesi

Java - equals() ve hashCode() Methodları

Bu yazimda equals() ve hashCode() methodlarinin ne ise yaradigini gorecegiz. Oncelikle asagidaki ornek uzerinden gidelim.

import java.util.HashMap;
import java.util.Map;
public class Example {
 public static void main(String[] args) {
  Person p1 = new Person(1);
  Person p2 = new Person(1);

  Map<Person, String> pMap = new HashMap<Person, String>();
  pMap.put(p1, "Jon");
  pMap.put(p2, "Jon");
  
  System.out.println(pMap.size());
  
  Integer i1 = new Integer(1);
  Integer i2 = new Integer(1);
  Map<Integer, String> iMap = new HashMap<Integer, String>();
  
  iMap.put(i1, "1");
  iMap.put(i2, "1");
  
  System.out.println(iMap.size());
 }
}

class Person{
 int id;
 
 public Person(int id) {
  this.id = id;
 }
}

Ornegimizi aciklamaya calisalim. Person adinda id si olan bir classimiz var. Ve ben main classimda bir ayni id li iki ayri Person objesi olusturuyorum ve bunlari map e ekliyorum, soru ise map in size i nedir.

Ayni seyi Integer icin de yapiyoruz. Ayni degerli iki ayri integer objesi olusturuyoruz ve bir map olusturup bu iki integer i ekliyoruz. Ikisi de ayni degeri iceriyor. Ayni sekilde size i print ettiryoruz.

Sonucun ne olmasini bekleriz.

Output:
2
1

Yani person Map te ayni degeri icermesine ragmen size 2 dondu ama integer map te ayni degeri icerdigi icin 1 dondu. Bu nasil oldu.


Aciklama

Integer bir Wrapper class ve icerisinde hashCode ve equals metodlari tanimli olarak geliyor. O yuzden hashCode ve equals methodlari calistigi icin ayni degeri yeniden eklememize izin vermedi.

Ama Person classini biz yazdik ve icinde hashCode ve equals methodlari yok. Bu yuzden de bir kontrol yapmadi ve ayni degerleri ekleyebildik. Olmasi gereken once hashCode degerleri esit mi diye bakacak esitse equals methodu ile contentleri esit mi diye bakacak.

O yuzden Person classina hashCode() ve equals() methodlarini ekleyelim. Istersek kendimiz yazabiliriz istersek IDE den implement edebiliriz.

package com.examples;

import java.util.HashMap;
import java.util.Map;

public class Example {

 public static void main(String[] args) {
  Person p1 = new Person(1);
  Person p2 = new Person(1);
  
  Map pMap = new HashMap();
  pMap.put(p1, "Jon");
  pMap.put(p2, "Jon");
  
  System.out.println(pMap.size());
  
  Integer i1 = new Integer(1);
  Integer i2 = new Integer(1);
  Map iMap = new HashMap();
  
  iMap.put(i1, "1");
  iMap.put(i2, "1");
  
  System.out.println(iMap.size());
 }
}

class Person{
 int id;
 
 public Person(int id) {
  this.id = id;
 }
 @Override
 public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + id;
  return result;
 }
 @Override
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (getClass() != obj.getClass())
   return false;
  Person other = (Person) obj;
  if (id != other.id)
   return false;
  return true;
 } 
}

Bu durumda output ikisi icinde 1 olacak. hashCode ve equals methodlari sayesinde ayni degeri eklememize izin vermeyecek.



24 Kasım 2019 Pazar

LinkedList Insert / Insert Given Position / Print List


public class AddPositiontoNode {
 Node head;
 static class Node {
  Node next;
  int data;
  Node(int d) {
   this.data = d;
  }
 }
 public static AddPositiontoNode insertNode(AddPositiontoNode list, int d) {
  Node newNode = new Node(d);
  newNode.next = null;
  if (list.head == null) {
   list.head = newNode;
  } else {
   Node currNode = list.head;
   while (currNode.next != null) {
    currNode = currNode.next;
   }
   if (currNode.next == null) {
    currNode.next = newNode;
   }
  }
  return list;
 }
 public static AddPositiontoNode insertGivenPosition(AddPositiontoNode node, int position, int data) {
  Node newNode = new Node(data);
  int index = 1;
  Node currNode = node.head;
  if (position == 1) {
   newNode.next = node.head.next;
   node.head = newNode;
  } else {
   while (index + 1 != position) {
    index++;
    currNode = currNode.next;
   }
   if (index + 1 == position) {
    newNode.next = currNode.next;
    currNode.next = newNode;
   } else {
    newNode.next = currNode.next;
    currNode.next = newNode;
   }
  }
  return node;
 }
 public static void printList(Node head) {
  Node currNode = head;
  while (currNode != null) {
   System.out.println(currNode.data);
   currNode = currNode.next;
  }
 }
 public static void main(String[] args) {
  AddPositiontoNode node = new AddPositiontoNode();
  node = insertNode(node, 1);
  node = insertNode(node, 2);
  node = insertNode(node, 4);
  node = insertNode(node, 5);

  printList(node.head);
  System.out.println("---------------------");
  node = insertGivenPosition(node, 3, 3);
  printList(node.head);
 }
}

Output :

1
2
4
5
---------------------
1
2
3
4
5

17 Kasım 2019 Pazar

Thread Safety HashMap

Merhaba,
Bu yazida thread safe hashmap ile ilgili ornek yapacagiz.
Once thread safe olmayan bir ornek yapalim.

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class UnsafeMap {
 public static void main(String[] args) throws InterruptedException {
  Map cricketMap = new HashMap();
  cricketMap.put("Australia", 349);
  cricketMap.put("India", 257);
  ExecutorService executorService = Executors.newFixedThreadPool(10);
  Runnable task = new Runnable() {
   @Override
   public void run() {
    incrementScore(cricketMap, "India");
   }
  };
  for(int i=0; i<100 :="" ap="" cricketmap.get="" executorservice.awaittermination="" executorservice.shutdown="" executorservice.submit="" i="" inal="" incrementscore="" india="" integer="" is="" ndia="" of="" private="" score="" static="" system.out.println="" task="" timeunit.seconds="" tring="" void=""> teamMap, String team) {
  Integer score = teamMap.get(team);
  teamMap.put(team, score +1);
 }
}

Yukaridaki ornekte India nin score unu 100 arttirdik. Sonucun 258 olmasini bekliyoruz ama her seferinde baska sonuc cikiyor.

Final score of India is : 353
Final score of India is : 352

gibi. Neden ?

Cunku 

since multiple threads try to modify the HashMap concurrently, the change done by one thread gets overridden by some other thread, and the output becomes non-deterministic.

Bunu onlemek icinse ornegimizi thread safe yapalim. Yani sadece ayni anda tek bir thread erisebilsin. Bunun icin yapacagimiz iki sey sunlar olmali :

  • Use the Collections.synchronizedMap() method to obtain a synchronized view of the HashMap.
  • Write the increment logic inside a synchronized block.
Son halde kodumuz su sekilde olur:

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class Safemap {
 public static void main(String[] args) throws InterruptedException {
  Map cricketScore = Collections.synchronizedMap(new HashMap());  
  cricketScore.put("Turkey", 52);
  cricketScore.put("Germany", 170);   
  //we are creating thread pool with size 10
  ExecutorService executorService = Executors.newFixedThreadPool(10);
  
  Runnable task = new Runnable() {   
   @Override
   public void run() {
    incrementScore(cricketScore, "Turkey");    
   }
  };
  for(int i=0; i<100 :="" ap="" cricketscore.get="" executorservice.awaittermination="" executorservice.shutdown="" executorservice.submit="" i="" inal="" incrementscore="" integer="" is="" of="" private="" score="" static="" system.out.println="" task="" timeunit.seconds="" tring="" turkey="" urkey="" void=""> scoreMap, String team) {
  synchronized (scoreMap) {
   Integer score = scoreMap.get(team);
   scoreMap.put(team, score +1);
  }
 }
}
Turkiyenin score unu 100 arttirdik. Threas safe oldugu icin her zaman 152 donecektir.

Final score of Turkey is : 152

14 Kasım 2019 Perşembe

Interthread Communication


Asagidaki ornegi incelemeye baslayalim.

Oncelik A adli bir classimiz var. Setleme ve getleme yapmasi icin put ve get methodlarimiz var. Her 2 methodumuz da degerlerimizi anlik olarak yazdirdik.

Daha sonra ise Producer ve Consumer adli classlarimiz var. Producer deger setlemek Consumer ise getlemek icin. Producer icinde sonsuz bir dongu var ve her seferinde degeri +1 i olarak setliyor.

Consumer icinde de sonsuz bir dongu var ve degeri get ediyor. Bu islemleri run() methodu icinde yapiyoruz. Bu run methodunun cagirilmasi icinse Thread e ihtiyacimiz var. O yuzden constuctor icinde thread olusturuyoruz ve start methodunu cagiriyoruz cunku start() methodu run i cagiracaktir.


class A{
 int num;
 // we need two methods here. one for set value and one for get the value
 public void put(int num) {
  System.out.println("Put : "+ num);
  this.num = num;
 } 
 public void get() {
  System.out.println("Get : "+ num);
 }
}
class Producer implements Runnable{ 
 A a;  
 public Producer(A a){
  this.a = a;
  // for Producer to call run method we need to create Thread. with start method, it will call run  
  Thread t = new Thread(this, "Producer");
  t.start();
 }
 public void run() {
  int i=0;
  // we have infinite loop here. every loop we set the value as i++
  while(true) {
   a.put(i++);
   try { Thread.sleep(1000); } catch(Exception e) {}
  }
 }
}
class Consumer implements Runnable{
 A a; 
 public Consumer(A a) {
  this.a = a;
  Thread t = new Thread(this, "Consumer");
  t.start();
 } 
 public void run() {
  while(true) {
   a.get();
   try { Thread.sleep(1000); } catch(Exception e) {}
  }
 }
}
public class ThreadCommunication {
 public static void main(String[] args) {
  A a = new A();
  new Producer(a);
  new Consumer(a);
 }}

Bunu calistirdigimiz da ise aldigimiz sonuca bakalim:
Put : 0
Get : 0
Get : 0
Put : 1
Put : 2
Get : 1
Put : 3
Get : 2
Put : 4
Get : 3
Put : 5
Get : 4


Gordugumuz gibi 0 icin 2 kez Get calismis. Bizim istedigimiz bu degildi. once setlesin sonra getlesin ve bu sirayla olsundu.


Bunun icin boolean bir degisken olusturacagiz ve default olarak false a setlicez.
put() icinde kontrol edelim. eger true ise yani zaten setlenmisse bizim setlememize gerek yok demektir. Bu durumda Consumer in degeri consume etmesini beklicez. Bunu wait() methodu ile yapicaz. Simdi su bilgiyi hatirlayalim.

Sleep() methodu kullandigimizda thread wait state ine gecer ve o sure bitince tekrar runnable olur. ama wait() ile oyle bir durum yok. Bekler surekli. Bu durumda bunu birilerine haber verelim ki bekledigini anlasin. Bunu notify() methodu ile yapariz.

Bunun icin haber vermemiz gereken consumer dur. Bunun icin setlendikten sonra notify() cagiriyoruz ve notify methodu consumer i notify edicek.

Simdi ayni islemleri get icin dusunelim. Eger valueSet degeri false gelirse deger setlenmemis demektir. Bu durumda setlenmemis degeri okuyamayiz. Beklememiz lazim. Kimi ? Producer i. yine wait cagirdik. Eger deger setlenmis ile okuyalim.

Ayrica wait() cagirdigimiz tum methodlarin synchronized olmasi zorundadir.
Kodumuzun son hali asagidaki gibi olacaktir.

Ayrica sleep surelerini de degistirdim. 0.5 saniyede setliyor ve consumer 2 saniyede okuyor. bu durumda consumer in okumasini beklicez, o okumadan asla setlemeye gecmicek.

class A{
 int num;
 // to keep track the value we created a boolean value
 boolean valueSet = false;
 // we need two methods here. one for set value and one for get the value
 public synchronized void put(int num) {
  while(valueSet) {
   // eger valueSet true ise deger zaten setlenmistir.
   // bir daha setlemeye gerek yok.
   // o yuzden burada beklicez yani wait cagiricaz
   // with wait method it will wait for consumer to consume the value
   
   try { wait(); } catch(Exception e) {}
  }  
  System.out.println("Put : "+ num);
  this.num = num;
  valueSet = true;
  notify();
 } 
 public synchronized void get() {
  while(!valueSet) {
   try { wait(); } catch(Exception e) {}
  }
  System.out.println("Get : "+ num);
  valueSet = false;
  notify();
 }
}
class Producer implements Runnable{ 
 A a;  
 public Producer(A a){
  this.a = a;
  // for Producer to call run method we need to create Thread. with start method, it will call run
  Thread t = new Thread(this, "Producer");
  t.start();
 }
 public void run() {
  int i=0;
  // we have infinite loop here. every loop we set the value as i++
  while(true) {
   a.put(i++);
   try { Thread.sleep(500); } catch(Exception e) {}
  }
 }
}
class Consumer implements Runnable{
 A a; 
 public Consumer(A a) {
  this.a = a;
  Thread t = new Thread(this, "Consumer");
  t.start();
 } 
 public void run() {
  while(true) {
   a.get();
   try { Thread.sleep(2000); } catch(Exception e) {}
  }
 }
}
public class ThreadCommunication {
 public static void main(String[] args) {
  A a = new A();
  new Producer(a);
  new Consumer(a);
 }}


Output:
Put : 0
Get : 0
Put : 1
Get : 1
Put : 2
Get : 2
Put : 3
Get : 3
Put : 4
Get : 4
Put : 5
Get : 5
Put : 6

9 Kasım 2019 Cumartesi

Multithreading Java

5 defa Hi, 5 defa Hello yazdiralim.



Output: Hi
Hi
Hi
Hi
Hi
Hello
Hello
Hello
Hello
Hello


Gordugumuz gibi 5 kez Hi ve Hello yazdi. Simdi ise her bir yazmadan once biraz beklesin diye bi thread sleep koyalim. 500 verdim yani 500 ms.




Kodumuz bu sefer yukaridaki gibi. 500 ms arayla print ediyor. Burada belirtmek istedigimiz sey kodumuz yine ayni seyi yapiyor ancak Hi yazmasinin bitmesini bekliyor. Bitmeden Hello ya gecmiyor. Bizim istedigimiz ise ikisi ayni anda calisabilsin, birbirini bloklamasin.

O yuzden burada thread kullanacagiz. Her classimiz Thread classini extend ederse classlarimiz Thread haline gelmis olur. Eee Thread classlarinda mutlaka run() olmali ki islemimiz orada calissin. O yuzden show() metodunu run() haline getiriyoruz. ve main threadimiz obj1.start() dememiz lazim. start() cagirdigimiz anda gidip run() methodunu calistirir.



Output  :
Hi
Hello
Hi
Hello
Hello
Hi
Hi
Hello
Hello
Hi

Gordugumuz gibi artik 2 thread birbirini beklemiyor ve ayni anda calisabiliyor. Hatta o kadar ayni ana denk gelmis ki ardarda 2 tane Hello goruyoruz. Ayni ana gelme durumlarinda schedular a gidilir ve schedular hangisi daha kisa ve kolaysa onu secer. Ancak burada 2 methodumuz da ayni islemi yaptigi icin random olarak Hello secilmis.


Interfacelerle Calismak

Javada asagidaki gibi bir kullanim yoktur.

class A extends B, C

Sadece bir tane extend edebiliriz.

O halde soyle bir sey yapmak yerine

class Ornek extends A, Thread { (hatali)

asagidaki gibi yapabiliriz.

class Ornek extends A implements Runnable {

Yani neymis : Thread olusturmanin 2 yontemi varmis.

1. extends Thread diyerek

2. implements Runnable diyerek

Hangisi isimizi gorurse onu kullanmaliyiz.

O halde ornegimizi bir de bu sekilde deneyelim.

Ancak artik classlarimiz Thread tipinde olmadigi icin obj1.start() diyemeyiz. Hata verir. Runnable da o sekilde bir method yok.

O zaman Thread olusturmamiz lazim.

Thread t1 = new Thread(obj1);
t1.start();

iste bu calisir. O halde kodumuzu duzenleyip yeniden deneyelim.



Output:
Hi
Hello
Hello
Hi
Hello
Hi
Hi
Hello
Hello
Hi

Lambda Expressions

Simdi de bu yazmis oldugumuz daha kisa ve daha efektif hale getirmeye calisalim.

Hi ve Hello adinda iki class yazdik ve ikisinin de yaptigi sey sadece Runnable i implement etmek. O halde bunlara gerek yok.Thread icinde de ayni islemi yapabiliriz.



Simdi de bunu lambda haline getirelim. Yani method isimlerine ve parantezlere gerek yok.

O durumda da soyle olur:


Son durumda ise kodumuz asagidaki gibi olur ve ayni islevi daha efektif olarak yapar.


Output:

Hi
Hello
Hello
Hi
Hi
Hello
Hi
Hello
Hi
Hello

8 Kasım 2019 Cuma

Thread Safety

Bu yazimda Thread Safety konusunu ele alacagim. Mutation diye bir kavram var ne oldugunu biliyor muyuz ? Tek tek gidelim.

Mutable ve Immutable degiskenlerden bahsedelim. Mutable degisebilen demektir. Immutable ise degismez. Ornegin javadaki String classina bakalim.

String ornek = "Gamze";
ornek.toUpperCase();
System.out.println(ornek);

Sonucun ne olmasini bekliyoruz ? Sonuc Gamze dir. Neden diyecek olursak String immutable yani degismez oldugu icin. Eger degistirmek istersek yeni bir degiskene atayarak kullanmamiz lazim.

Thread konusuna gececek olursak eger ayni anda birden fazla islem gerceklestirmek istiyorsak bunu threadler yardimiyla yapabiliriz. Her bir threadle farkli bir is yapip, birden fazla threadle isimizi gerceklestirebiliriz.

Simdi bu iki konuyu birbiriyle baglayalim. Bir program yazarken amacimiz datalari degistirmektir, cunku istedigimiz islemi bu sekilde yapabiliriz. Yani mutation bizim icin onemli. Multithreading de bizim icin onemli ki birden fazla isi ayni anda yapabilelim.

Bir tane shared datamiz oldugunu ve birden fazla thread in buna erismeye calistigini dusunelim. Tabiki get etmeye calisirken sorun yok. Ama bu threadler datayi degistirmeye calistigi anda problem ortaya cikar. Buna Race Condition denir. Java da immutable objeler thread safe dir. Zaten kimse degistiremedigi icin sorun olusturmazlar.

public class ThreadExample {
 static class Counter {
  int count;  
  public void increment() {
   count ++;
  }
 } 
 public static void main(String[] args) {
  Counter c = new Counter();
  for(int i=0; i< 2000; i++) {
   c.increment();
  }  
  System.out.println(c.count);
 }}
Ornegimizde gordugumuz gibi increment adinda bir fonksiyonumuz var. Datamizi degistirmeye calisiyor. 2000 defa datayi degistirmeye calisalim. Sonuc olarak ne bekliyoruz. 2000 

Burda bir sorun yok. Simdi burada multiple thread kullanmaya calisalim. 2 thread kullanalim ve ayni sonucu yani 2000 i elde etmeye calisalim. Bu durumda ne olmali. 1. thread i 1000, 2.threadi 1000 defa cagirdigimizda 2000 cikmasini bekleriz.

 public static void main(String[] args) throws InterruptedException {
  Counter c = new Counter();
  Thread thread1 = new Thread(new Runnable() {   
   @Override
   public void run() {
    for(int i=0; i< 1000; i++) {
     c.increment();
    }
   }
  });  
  Thread thread2 = new Thread(new Runnable() {   
   @Override
   public void run() {
    for(int i=0; i< 1000; i++) {
     c.increment();
    }
   }
  });  
  thread1.start();
  thread2.start();  
  // join() cagirmamizin sebebi bu 2 thread bitene kadar beklemesi icin
  thread1.join();
  thread2.join();  
  System.out.println(c.count);
 }


2 threadimiz var ve her biri 1000 defa calisiyor. 2000 sonucunu gormeyi bekliyoruz, ama her calistirdigimizda sonuc degisiyor. 2000 de gelebiliyor 1550 de 1200 de.


Bunun sebebi datamizi degistiren increment methodunun thread safe olmamasi. Ayni anda count degiskenine 2 thread de ulasmaya calisiyor ve degeri degistiriyor.

Bunu onlemek icin 2 yontem var.

1. Synchronized  Keyword

Increment methoduna sychronized eklersek ayni anda threadin datamiza erismesine ve degistirmesine izin vermez.

public synchronized void increment() {
 count ++;
}

Bu durumda surekli 2000 sonucunu elde edebiliriz.

2. Atomic Integer


AtomicInteger count = new AtomicInteger();
public synchronized void increment() {
 count.incrementAndGet();
}


Bu 2 yontemle thread safety e erisebiliriz.

6 Kasım 2019 Çarşamba

HashMap Examples

 Given a string array item[] and an integer array price[] where price[i] is the price of the item[i] when purchased from the ith shop. The task is find the lowest, the highest and the average price value for all the purchsed items.

Input: item[] = {“toy”, “pen”, “notebook”, “pen”}, price[] = {2, 1, 3, 2}
Output:
Item Min Max Average
pen 1 2 1.5
toy 2 2 2.0
notebook 3 3 3.0


Input: item[] = {“car”, “car”}, price[] = {20000, 30000};
Output:
Item Min Max Average
car 20000 30000 25000.0


import java.util.HashMap;import java.util.Map;

public class Example01 {

        static class Item{
        int min, max, total, sum;
        Item(int price){
        min = price;
        max = price;
        total = 1;
        this.sum = price;
        }
        }
       
        static void findPrices(String item[], int price[], int n){
        HashMap<String, Item> map = new HashMap<>();
       
        for(int i=0; i<n; i++){
        if(map.containsKey(item[i])){
                Item currItem = map.get(item[i]);
                currItem.min = Math.min(currItem.min, price[i]);
                currItem.max = Math.max(currItem.max, price[i]);
                currItem.total++;
                currItem.sum += price[i];
        } else{
                Item currItem = new Item(price[i]);
                map.put(item[i], currItem);
        }
        }
       
        System.out.println("Item Min Max Avr");
        for(Map.Entry<String, Item> ob : map.entrySet()){
        String key = ob.getKey();
        Item currItem = ob.getValue();
        System.out.println(key + " " + currItem.min + " " + currItem.max + " " + ((float)currItem.sum/ (float)currItem.total));
        }
       
        }
       
        public static void main(String[] args) {
        String item[] = { "toy", "pen", "notebook", "pen" };
            int n = item.length;
            int price[] = { 2, 1, 3, 2 };
     
            findPrices(item, price, n);

        }

}





----


import java.util.HashMap;

public class Example03 {

        public static void main(String[] args) {

        HashMap<String, Integer> map = new HashMap<>();
        map.put("key1", 1);
        map.put("key2", 2);
        map.put("key3", 3);
        map.put("key4", 4);
       
        System.out.println("Hashmap1: " + map.toString());
       
        map.replaceAll((key, oldValue) -> oldValue * oldValue);

        System.out.println("new Hashmap : " + map.toString());
       
       
        HashMap<String, Integer> map2 = new HashMap<>();
        map2.put("A", 2000);
        map2.put("B", 2001);
        map2.put("C", 1994);
       
        System.out.println("Year of birth: " + map2.toString());
       
        map2.replaceAll((key, yearOfBirth) -> 2019 - yearOfBirth);
       
        System.out.println("Ages: " + map2.toString());
        }

}

---------
Given an array arr[] having 4 integer digits only. The task is to return the maximum 24 hour time that can be formed using the digits from the array.
Note that the minimum time in 24 hour format is 00:00, and the maximum is 23:59. If a valid time cannot be formed then return -1.

Input: arr[] = {1, 2, 3, 4}
Output: 23:41


Input: arr[] = {5, 5, 6, 6}
Output: -1





import java.util.HashMap;

public class MaxTime {

       
       
        public static void main(String[] args) {
    int arr[] = {0,0,0,9};
    System.out.println(getMaxTime(arr));
   
    int arr2[] = {1,2,3,4};
    System.out.println(getMaxTime(arr2));
   
    int arr3[] = {5,6,7,8};
    System.out.println(getMaxTime(arr3));
   
        }

        static String getMaxTime(int arr[]) {
       
        String time = "";
        boolean possible = false;
             
        HashMap<Integer, Integer> freqs = new HashMap<>();
       
        freqs = findFreqs(arr);
       
        //for hour
        for(int i=2; i>= 0; i--){
        if(hasDigit(freqs, i)){
              possible = true;
              time += i;
              break;
        }
        }
       
        if(possible==false){
        return "No Possible with That input";
        }   
        possible = false;
       
        if(time.charAt(0) == '2'){
        for(int i=3; i>=0;i--){
                if(hasDigit(freqs, i)){
                time += i;
                possible = true;
                break;
                }
        }
        } else{
        for(int i=9; i>=0;i--){
                if(hasDigit(freqs, i)){
                time += i;
                possible = true;
                break;
                }
        }
        }
       
       
        if(possible==false){
        return "No Possible with That input";
        }
       
        possible = false;
        time += " : ";
       
        for(int i=5; i>=0;i--){
                if(hasDigit(freqs, i)){
                time += i;
                possible = true;
                break;
                }
        }
       
        if(possible==false){
        return "No Possible with That input";
        }
       
        possible = false;
       
        for(int i=9; i>=0;i--){
                if(hasDigit(freqs, i)){
                time += i;
                possible = true;
                break;
                }
        }
       
        if(possible==false){
        return "No Possible with That input";
        }
       
        return time;
        }


        private static HashMap<Integer, Integer> findFreqs(int[] arr) {
       
        HashMap<Integer, Integer> freqs = new HashMap<>();
       
        for(int i=0; i<arr.length; i++){
        if(!freqs.containsKey(arr[i])){
                freqs.put(arr[i], 1);
        } else{
               
                freqs.replace(arr[i], freqs.get(arr[i])+1);
        }
        }
       
        return freqs;
        }

        private static boolean hasDigit(HashMap<Integer, Integer> map, int j) {
       
        if(map.containsKey(j) && map.get(j) >0){
        map.replace(j, map.get(j) -1);
        return true;
        }
       
        return false;
   
        }

}
----


import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class IterationExample {

        public static void main(String[] args) {
        int arr[] = {2, 4, 6, 8, 1, 6};
               
        HashMap<Integer, Integer> map = new HashMap<>();
       
        for(int i=0;i< arr.length; i++){
        map.put(arr[i], i);
       
        }
       
        for(Map.Entry<Integer, Integer> s : map.entrySet()){
        System.out.println(s.getKey() + "-" + s.getValue());
        }
       
        Iterator<Integer> it = map.keySet().iterator();
       
        while(it.hasNext()){
        Integer key = it.next();
        System.out.println(key + "/" + map.get(key));
        }
       
        }

}

public class AnagramExample {

 static boolean checkForAnagram(String s1, String s2) {
  if(s1.length() != s2.length()) {
   return false;
  }  
  HashMap charMap1 = new HashMap();
  for(int i =0;i< s1.length(); i++) {
   if(charMap1.containsKey(s1.charAt(i))) {
    charMap1.put(s1.charAt(i), charMap1.get(s1.charAt(i)) +1);
   } else {
    charMap1.put(s1.charAt(i), 1);
   }
  }
  HashMap charMap2 = new HashMap();
  for(int i =0;i< s2.length(); i++) {
   if(charMap2.containsKey(s2.charAt(i))) {
    charMap2.put(s2.charAt(i), charMap2.get(s2.charAt(i)) +1);
   } else {
    charMap2.put(s2.charAt(i), 1);
   }
  }  
  Iterator> iterator = charMap1.entrySet().iterator();
  while(iterator.hasNext()) {
   Map.Entry entryForMap1 = iterator.next();
   if(charMap2.containsKey(entryForMap1.getKey())) {
    if(!charMap2.get(entryForMap1.getKey()).equals(entryForMap1.getValue())) {
     return false;
    }
    
   }else {
    return false;
   }
  }
  return true; 
 } 
 public static void main(String[] args) {
  System.out.println(checkForAnagram("deneme", "silent")); 

 }
}


Java Comparator - Comparable Interface

Ornegin elimizde bir liste olsun ve biz bu listenin elemanlarini siralamak isteyelim. Bunu nasil yapacagimiz asagidaki ornekte gosterdim.

public class CompareElements {
 public static void main(String[] args) {
  List<String> nameList = new ArrayList<String>();
  nameList.add("helen");
  nameList.add("yasmin");
  nameList.add("andrew");
  nameList.add("craine");
  Collections.sort(nameList);
  System.out.println(nameList);
 }
}
Output:
[andrew, craine, helen, yasmin]

Ornekteki elemanlari gordugumuz gibi alfabetik siraya gore siraladik. Burada isimiz kolaydi cunku listede sadece tek tipte elemanimiz vardi. O da isim.

Simdi soyle bir case dusunelim. String tipinde isim yerine Person adinda bir classimiz olsun ve bu class in hem name hem de age attribute lari olsun. Ve ben istedigim zaman istedigim parametreye gore sirayalabileyim.

Oncelikle isme gore siramak istiyorum.


public class ComparableEx {

 public static class Person implements Comparable{
  private String name;
  private int age;
  public Person(String name, int age) {
   super();
   this.name = name;
   this.age = age;
  }
  public String getName() {
   return name;
  }
  public void setName(String name) {
   this.name = name;
  }
  public int getAge() {
   return age;
  }
  public void setAge(int age) {
   this.age = age;
  }  
  @Override
  public int compareTo(Person o) {
   return this.name.compareTo(o.name);
  }
 } 
 public static void main(String[] args) {  
  List personList = new ArrayList<>();
  personList.add(new Person("craine", 21));
  personList.add(new Person("yasmin", 12));
  personList.add( new Person("andrew", 15));
  personList.add(new Person("helen", 10));
  
  Collections.sort(personList);
  for(Person person:personList) {
   System.out.println(person.getName());
  }
 }}
Output:
andrew
craine
helen
yasmin


Gordugumuz gibi modelimiz Comparable Interface ini implement ediyor ve compareTo methodu icinde name'e gore siraliyoruz. Age icin yapmak istersek compareTo icinde age kullaniriz.

Simdi ise boyle tek tek degil de, yani her seferinde compareTo icini degistirerek degil de, istedigimiz an istedigimiz sekilde siralamaya bakalim. Bu durumda ise Comparator interface ini kullanacagiz.
public class ComparatorEx {

 public static class Person{
  private String name;
  private int age;
  public Person(String name, int age) {
   super();
   this.name = name;
   this.age = age;
  }
  public String getName() {
   return name;
  }
  public void setName(String name) {
   this.name = name;
  }
  public int getAge() {
   return age;
  }
  public void setAge(int age) {
   this.age = age;
  }
  
 }
 
 public static class NameComparator implements Comparator{

  @Override
  public int compare(Person o1, Person o2) {
   return o1.getName().compareTo(o2.getName());
  }  
 }
 
 public static class AgeComparator implements Comparator{

  @Override
  public int compare(Person o1, Person o2) {
   if(o1.getAge()>o2.getAge()) {
    return 1;
   } else if(o2.getAge() >o1.getAge()){
    return -1;
   }else {
    return 0;
   }   
  }  
 }
 public static void main(String[] args) {
  List personList = new ArrayList<>();
  personList.add(new Person("craine", 21));
  personList.add(new Person("yasmin", 12));
  personList.add( new Person("andrew", 15));
  personList.add(new Person("helen", 10));
  
  Collections.sort(personList, new NameComparator());
  for(Person p: personList) {
   System.out.println(p.getName()+ "->"+p.getAge());
  }
                System.out.println("--------");
  Collections.sort(personList, new AgeComparator());
  for(Person p: personList) {
   System.out.println(p.getName()+ "->"+p.getAge());
  }
 }
}
Output:
andrew->15
craine->21
helen->10
yasmin->12
--------
helen->10
yasmin->12
andrew->15
craine->21

Gordugumuz gibi her bir attribute icin bir class olusturup Comparator interface ini implement ettik ve ona gore siraladik.


3 Kasım 2019 Pazar

Ornek Soru

1. You are given an array and you need to find number of tripets of indices (i, j, k) such that the elements at those indices are in geometric progression for a given common ratio r and i < j < k.
For example, arr=\left[1,4,16,64\right]. If r=4, we have \left[1,4,16\right] and \left[4,16,64\right] at indices (0, 1, 2) and (1, 2, 3).
Function Description
Complete the countTriplets function in the editor below. It should return the number of triplets forming a geometric progression for a given r as an integer. countTriplets has the following parameter(s):
arr: an array of integers
r: an integer, the common ratio
Input Format
The first line contains two space-separated integers n and r, the size of arr and the common ratio.
The next line contains n space-seperated integers arr\left[i\right].
Constraints
1 \le n \le 10^5
1 \le r \le 10^9
1 \le arr\left[i\right] \le 10^9
Output Format
Return the count of triplets that form a geometric progression.

Sample Input 0
4 2
1 2 2 4
Sample Output 0
2
Explanation 0
There are 2 triplets in satisfying our criteria, whose indices are (0,1,3) and (0,2,3)
Sample Input 1
6 3
1 3 9 9 27 81
Sample Output 1
6
Explanation 1
The triplets satisfying are index (0,1,2)(0,1,3)(1,2,4)(1,3,4)(1,4,5) and (3,4,5).

Solution

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Soru03 {

  // Complete the countTriplets function below.
    static long countTriplets(List<Long> arr, long r) {

     Map<Long, Long> potential = new HashMap<>();
        Map<Long, Long> counter = new HashMap<>();
        long count = 0;
        for (int i = 0; i < arr.size(); i++) {
            long a = arr.get(i);
            long key = a / r;
            
            if (counter.containsKey(key) && a % r == 0) {
                count += counter.get(key);
            }
            
            if (potential.containsKey(key) && a % r == 0) {
                long c = potential.get(key);
                counter.put(a, counter.getOrDefault(a, 0L) + c);
            }
            
            potential.put(a, potential.getOrDefault(a, 0L) + 1); // Every number can be the start of a triplet.
        }
        return count;
    }

    public static void main(String[] args) throws IOException {
       
        long r = 3;
        List<Long> arr = new ArrayList<Long>();
        arr.add((long) 1);
        arr.add((long) 3);
        arr.add((long) 9);
        arr.add((long) 9);
        arr.add((long) 27);
        arr.add((long) 81);
        long ans = countTriplets(arr, r);
        
        System.out.println(ans);
       
    }
}

2. Harold is a kidnapper who wrote a ransom note, but now he is worried it will be traced back to him through his handwriting. He found a magazine and wants to know if he can cut out whole words from it and use them to create an untraceable replica of his ransom note. The words in his note are case-sensitive and he must use only whole words available in the magazine. He cannot use substrings or concatenation to create the words he needs.
Given the words in the magazine and the words in the ransom note, print Yes if he can replicate his ransom note exactly using whole words from the magazine; otherwise, print No.
For example, the note is "Attack at dawn". The magazine contains only "attack at dawn". The magazine has all the right words, but there's a case mismatch. The answer is .
Function Description
Complete the checkMagazine function in the editor below. It must print  if the note can be formed using the magazine, or .
checkMagazine has the following parameters:
  • magazine: an array of strings, each a word in the magazine
  • note: an array of strings, each a word in the ransom note
Input Format
The first line contains two space-separated integers,  and , the numbers of words in the  and the ..
The second line contains  space-separated strings, each .
The third line contains  space-separated strings, each .
Constraints
  • .
  • Each word consists of English alphabetic letters (i.e.,  to  and  to ).
Output Format
Print Yes if he can use the magazine to create an untraceable replica of his ransom note. Otherwise, print No.
Sample Input 0
6 4
give me one grand today night
give one grand today
Sample Output 0
Yes
Sample Input 1
6 5
two times three is not four
two times two is four
Sample Output 1
No
Explanation 1
'two' only occurs once in the magazine.
Sample Input 2
7 4
ive got a lovely bunch of coconuts
ive got some coconuts
Sample Output 2
No
Explanation 2
Harold's magazine is missing the word .

Solution
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class Soru04 {
 
 static void checkMagazine(String[] magazine, String[] note) {
  Hashtable<String, Integer> magazineMap = new Hashtable<String, Integer>();
        
        for(String s : magazine){
            if(magazineMap.containsKey(s)){
                magazineMap.put(s, magazineMap.get(s) + 1);
            }else{
                magazineMap.put(s, 1);
            }
        }
        boolean flag = true;         
        for(String s : note){
            if(!magazineMap.containsKey(s)){
               flag=false;
             break;
            }            
            int counter = magazineMap.get(s) - 1;
            
            if(counter == 0){
                magazineMap.remove(s);
            }else{
                magazineMap.put(s, counter);
            }
        }
         
        if(flag==false) {
        System.out.println("No");
        }else {
         System.out.println("Yes");
        }
  
    }
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  String s1[] = new String[] {"two", "times", "three", "is","not", "four"};
  String s2[] = new String[] {"two", "times", "two", "is", "four"};
  checkMagazine(s1, s2);
 }

}