ArÅŸiv

Buna etikete sahip yazılar; ‘java’

Java Enum Reverse Lookup

Perşembe, 17 May 2012 Yorum yapılmamış

Java 1.5 sürümü ile birlikte gelen Enum sınıfı genel itibariyle sabit verileri tanımlamak için kullanılır. 1.5 öncesi static final olarak tanımlanan sabit verilere denk gelir bir nevi. ÇoÄŸu zaman da bu sabit verilerle iliÅŸkilendirilmiÅŸ bir kod eÅŸlemesi yapılır. Döviz-döviz kodu, elemen-element simgesi, durum-durum kodu gibi…Bu kod tanımı Enum sınıfın yapılandırıcısına parametre geçilerek yapılır.

public enum Gender {
	Male("M"),
	Female("F");

	private String code;

	private Gender(String code) {
		this.code = code;
	}

	public String getCode() {
		return code;
	}
}

Herhangi bir enum değerin code alanına

Gender.Male.getCode()

ÅŸeklinde eriÅŸebiliriz.

Bahsetmek istediÄŸim ise bunun tam tersi durumda yani code alanından enum deÄŸere eriÅŸmek istediÄŸimiz durumda ne yapılabileceÄŸi. Bu durumun tam karşılığı “enum reverse lookup”.

public enum Month {
	JAN(1),FEB(2),MAR(3),APRIL(4),MAY(5),JUN(6),JUL(7),AUG(8),SEP(9),OCT(10),NOV(11),DEC(12);
	private int code;

	private Month(int code) {
		this.code = code;
	}

	public int getCode() {
		return code;
	}

}

şeklinde bir enum sınıfı olduğunu varsayarsak code alanından Month enum değerine

public Month getMonthFromCode(int code){
  for (Month month : Month.values()){
	  if (month.getCode() == code)
		  return month;
  }
  return null;

ÅŸeklinde eriÅŸilebilir.

Fakat her seferinde bir for döngüsü ile enum deÄŸerleri içinde dönmek yerine static bir Map tanımlayıp, bütün enum deÄŸeri-kod eÅŸleÅŸmeleri bu Map‘e koyularak, istenen enum deÄŸere her seferinde tek hamlede de eriÅŸlebilir. Şöyle ki;

public enum Month {

JANARY(1),FEBRUARY(2),MARCH(3),APRIL(4),MAY(5),JUNE(6),JULY(7),AUGUST(8),SEPTEMBER(9),OCTOBER(10),NOVEMBER(11),DECEMBER(12);
	private int code;

	private static Map enumCodeMap;
	static {
		enumCodeMap = new HashMap();
		for(Month month : Month.values()){
			enumCodeMap.put(month.getCode(), month);
		}
	}

	public static Month getMonthFromCode(int code){
		return enumCodeMap.get(code);
	}

	private Month(int code) {
		this.code = code;
	}

	public int getCode() {
		return code;
	}

}

şeklindeki bir enum tanımı sonrası

Month month = Month.getMonthFromCode(6);
//JUNE

denilebilir. Bu şekilde static bir tanım ile JVM, Month enum sınıfını yüklediğinde hazır hale gelmiş olan enumCodeMap değişkeni üzerinden her seferinde teknik olarak da, kod satırı olarak da tek hamle ile istenen enum değere erişilmiş olur.

Düzenleme : Bu durumla tam olarak örtüşen bir örnek, periyodik cetveldeki elementlerin tutulduÄŸu bir enum sınıfı olabilir. Element adı enum deÄŸeri, element simgesi kod olacak ÅŸekilde oluÅŸturulmuÅŸ olan bir Element enum sınıfı düşünülebilir. Altın’ın simgesi olan “Au” ya eriÅŸmekten ziyade, simgesi “Au” olan elemente eriÅŸmek lazım olduÄŸu durumlarda bu yöntem kullanılabilir

FacebooktwitterlinkedinmailFacebooktwitterlinkedinmail
Kategoriler:Java Etiketler:, , ,

Java’da TimeUnit Kullanımı

Pazartesi, 23 Nis 2012 1 yorum

Yeni farkına varıyorum ki meÄŸer Java’nın 1.5 ile beraber gelmiÅŸ TimeUnit diye bir enum sınıfı varmış. Åžu can sıkıcı, her seferinde tekrar tekrar yapmak zorunda kalabildiÄŸimiz zaman dönüşümü iÅŸlerini üstlenmiÅŸ. Gün, saat, dakika, saniye, milisaniye ve nanosaniye cinsinden zaman birimlerini birbirine dönüştürüveriyor.

Şöyle ki;

package com.selman;

import java.util.concurrent.TimeUnit;

public class TimeUnitTests {
	public static void main(String[] args) throws InterruptedException {
		long baslangic = System.currentTimeMillis();
		Thread.sleep(1300);
		long bitis = System.currentTimeMillis();
		
		//baslangic ile bitis arasindan gecen zamanin milisaniye cinsinden degeri 
		System.out.println(TimeUnit.MILLISECONDS.toMillis(bitis) - TimeUnit.MILLISECONDS.toMillis(baslangic) + " ms");
		//baslangic ile bitis arasindan gecen zamanin saniye cinsinden degeri 
		System.out.println(TimeUnit.MILLISECONDS.toSeconds(bitis) - TimeUnit.MILLISECONDS.toSeconds(baslangic) + " sn");
		
		
		//48 saatin gun cinsinden degeri 
		System.out.println(TimeUnit.DAYS.convert(48, TimeUnit.HOURS) + " gun");

		//10 gunun saat cinsinden degeri 
		System.out.println(TimeUnit.HOURS.convert(10, TimeUnit.DAYS) + " saat");
		
		//3656 saniyenin dakika cinsinden degeri
		System.out.println(TimeUnit.MINUTES.convert(3656, TimeUnit.SECONDS) + " dakika");
	}
}
/*--------*/
//1297 ms
//1 sn
//2 gun
//240 saat
//60 dakika

FacebooktwitterlinkedinmailFacebooktwitterlinkedinmail

Java ile IMDB’den film bilgisi almak

Çarşamba, 09 Kas 2011 Yorum yapılmamış

Her ÅŸey harici diskte yer açmaya çalışmakla baÅŸladı : ) Önceleri adından gözüme kestirdiÄŸim, şöyle basmakalıp Hollywood aksiyon veya romantik komedi türü filmleri imdb’de bir göz attıktan sonra siliyordum. Sonraları bu iÅŸ can sıkıcı olmaya baÅŸladı. Yok mudur bunun bir API’si, topluca bulayım bu filmleri de külliyen uçurayım kellerini falan diye bakmaya baÅŸladım. Nihayetinde eli yüzü düzgün, inciÄŸi boncuÄŸu olmayan bir servis buldum. Åžurada sunulan servis ile ilgili linke film adı ve/veya yılını parametre olarak geçtiÄŸinizde film bilgileri json formatında bir nesne olarak dönüyor. Geriye json formatındaki bu nesneyi ayrıştırmak kalıyor. Bunun için de halihazırda API’ler mevcut.

Şöyle ki;

package com.imdbInfo.base;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;

import net.sf.json.JSONObject;
import net.sf.json.JSONSerializer;

public class BasicTest {


private static final String BASIC_API_URL = "http://www.imdbapi.com/?";
private static final String TITLE_PARAM = "t=";
@SuppressWarnings("unused")
private static final String YEAR_PARAM = "&y=";

public static void main(String[] args) {


try {

String titleToSearch = URLEncoder.encode("Forrest Gump","UTF-8");

String text = getJSONStringOf(BASIC_API_URL + TITLE_PARAM + titleToSearch);

JSONObject jSonObject = (JSONObject) JSONSerializer.toJSON(text);

String title = jSonObject.getString("Title");
int year = jSonObject.getInt("Year");
int votes = jSonObject.getInt("Votes");
double rating = jSonObject.getDouble("Rating");
String genre = jSonObject.getString("Genre");
//Runtime, Director vs.
System.out.println("Title:" + title + "\nYear:" + year + "\nVotes:" + votes + "\nRating:" + rating + "\nGenre:" + genre);

}
catch (Exception e) {

//Movie not found !
e.printStackTrace();

}

}

public static String getJSONStringOf(String urlSpec) throws Exception {

URL url = new URL(urlSpec);
URLConnection connection = url.openConnection();

BufferedReader reader = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
String line = "";
StringBuilder builder = new StringBuilder();
while ((line = reader.readLine()) != null) {

builder.append(line);

}

return builder.toString();

}

}

Title:Forrest Gump
Year:1994
Votes:325985
Rating:8.6
Genre:Drama, Romance

diyerek filmin bilgilerini almış oluyoruz. Bunların içinde film adı, yapım yılı, türü, kullanılan oy sayısı, puan, yönetmen, oyuncular, süre ve sair filmle ilgili bir sürü bilgi bulunuyor.

Bundan sonra eldeki filmleri bu servisten alınan bilgiye göre sınıflandırmak kalıyor. Ki iÅŸin keyifli kısmı da orası : ) Yalnız ÅŸunu belirtmemde fayda var. Bu servisin elindeki veri imdb’nin yayınlamış olduÄŸu film veritabanından alınıyor. Sanırım biraz eski. AraÅŸtırmadım ama tahminimce bir kaç ay kadar. Ziyanı yok : )

Kodu bu haliyle kullanabilmek için projenin ‘classpath’ inde commons-beanutils,commons-collections-3.2.1, commons-lang, commons-logging, ezmorph-1.0.5 ve json-lib-2.4-jdk15 jar’larının bulunması gerekliyor.

Daha bir eli yüzü düzgün ve gerekli jar’ları barındıran kod örneÄŸi ÅŸuradan indirilip incelenebilir, Eclipse’e import edilebilir.

FacebooktwitterlinkedinmailFacebooktwitterlinkedinmail

Java’da listeleri generic olarak gruplamak

Cuma, 07 Eki 2011 Yorum yapılmamış

Kod yazarken bir listenin elemanlarını belirli bir alana göre gruplamak sıkça yapılan işlerden biridir. Personelleri işe giriş tarihine göre veya arabaları modelinin tipine göre gruplamak gibi. Gruplanan bu veriler de genel olarak Map türü bir veri yapısında tutulur. Bu işi genel(generic) olarak yapabilen ve gruplamaya kriter olan alanın seçiminde aşağı doğru dallanabilen bir metot kod tekrarını oldukça azaltması açısından faydalı olabilir. Sırf ben biliyorum çalıştığım projede bu işi kaç kere yaptığımı : )

Bu kodu kullanabilmek için classpath’e commons-beanutils.jar ve commons-logging.jar’ı eklemek gerekiyor.

Ayrıca eclipse projesi şuradan indirilip incelenebilir, import edilebilir.

public static <E, T> Map<E, List<T>> group(List<T> listToGroup, String groupingCriteria) {

Map<E, List<T>> grupMap = new HashMap<E, List<T>>();
for (T item : listToGroup) {
try {
E e = (E) BeanUtils.getProperty(item, groupingCriteria);
if (grupMap.containsKey(e)) {
grupMap.get(e).add(item);
} else {
List<T> list = new ArrayList<T>();
list.add(item);
grupMap.put(e, list);
}
} catch (IllegalAccessException exception) {
throw new RuntimeException(“Error in grouping !” + exception.getMessage());
} catch (InvocationTargetException exception) {
throw new RuntimeException(“Error in grouping !” + exception.getMessage());
} catch (NoSuchMethodException exception) {
throw new RuntimeException(“Error in grouping !” + exception.getMessage());
}

}
return grupMap;

}

FacebooktwitterlinkedinmailFacebooktwitterlinkedinmail

String.substring() ilginçliği

Salı, 25 Oca 2011 Yorum yapılmamış

Benim de geçenlerde şuradaki bir blog yazısından öğrendiğim String sınıfının substring() metodu ile ilgili ilginç bir durumdan bahsedeyim. Yazacaklarımın çoğu çeviri değerinde.

String a = “abcdefgh”;
a = a.substring(0,3);

şeklinde bir kod ile başlangıçta oluşturduğumuz String tipinde a nesnesinin ilk 3 karakterini ayrıştırıp yine kendisine atamış oluyoruz. Oluşan nesne yeni bir String nesnesidir. Çünkü String değişmez(immutable) bir tiptir. Bir kez oluşturulduktan sonra değişmezler yani. Integer, Double gibi ilkel tipleri sarmalayan tipler de öyledirler.

String nesnesinde;

value; char[] tipinde bir deÄŸiÅŸken. String nesnesinde bulunan karakterleri tutuyor.
count;int tipinde bir değişken. String nesnesinde bulunan karakter sayısını tutuyor.
offset;int tipinde bir deÄŸiÅŸken. String nesnesinin ilk karakterinin indeksini tutuyor.

ÅŸeklinde 3 alan bulunuyor.

substring() iÅŸlemi ile char[] dizisi (value) yeni oluÅŸan String nesnesine doÄŸrudan kopyalanıyor. Fakat count ve offset alanlarına uygun karşılıkları atanıyor. Dolayısıyla a nesnesini System.out.print(a); ÅŸeklinde konsola yazdıracak olursak “abc” deÄŸerlerini görüyoruz. Garip olan ÅŸu ki Reflection ile a nesnesinin sahip olduÄŸu karakter dizisine ulaÅŸtığımızda gördüğümüz deÄŸer “abcdefgh”. (Reflection ile nasıl nesnenin gerçek “value” deÄŸerini gördüğümüzün çok önemi olmadığı için kod örneÄŸini yazmaya gerek yok hani). Buradan oluÅŸan yeni String nesnesinin count ve offset deÄŸerleri farklı olsa da karakter dizisinin birebir kopya olduÄŸunu anlıyoruz. Örnek koda ÅŸuradan bakılabilir.

Bu durum hafıza kullanımında gereksiz şişmelere yol açabiliyor. Özellikle de sık sık substring() metotu ile büyük String nesneleri ayrıştıran bir işlem varsa. Yeri gelmişken bir String nesnesinin hafızada ne kadar yer kapladığını da şu şekilde hesaplıyoruz.

Yukarıda bahsettiÄŸimiz int tipinde count ve offset deÄŸiÅŸkenlere ilave olarak bir de hashCode için int tipinde bir deÄŸiÅŸken tutuluyor. Bu 3 int tipindeki deÄŸiÅŸken 4’er baytdan 12 bayt, nesnenin “object header” denen kimlik bilgisi de 8 bayt yer kaplıyor. BoÅŸ karakter dizisi olan char[] deÄŸiÅŸkeni de 8 bayt karater dizisi, 4 bayt dizinin uzunluÄŸunu tutmak için bulunan deÄŸiÅŸken, ve 4 bayt da toplamda 16’nın 12’ye en yakın katı olan 16’ya tamamlamak için olmak üzere; 16 bayt yer kaplıyor. 12+8+16=36’yı da bir sonraki 8’in katı olan 40’a tamamlıyoruz. Bu da boÅŸ bir String nesnesinin 40 bayt yer kapladığını gösteriyor.

Kabaca şöyle bir formül çıkıyor;
– String nesnesinde bulunan karakter sayısını iki ile çarp,
– 38 ekle,
– Sonuç 8’in katı bir sayı deÄŸilse sonraki ilk 8’in katı olan sayıya yuvarla

20 karakter içeren bir String nesnesi;
20*2 = 40,
40+38=78,
78’i de 8’in sonraki ilk katına tamamlarsak ->80 bayt yer kaplıyor

Mevzuya dönecek olursak bu gibi hafıza şişmelerini engellemek için substring() metodundan dönen String nesnesini yine bir String nesnesinin yapılandırıcısına parametre olarak geçiyoruz.

String a = new String(a.substring(0,3));

Bu arada aynı durum String sınıfının trim() metodu için de geçerli. Farkında olmaya değer bir ilginçlik.

FacebooktwitterlinkedinmailFacebooktwitterlinkedinmail