Arşiv

‘Java Teknolojileri’ kategorisi için arşiv

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

Eclipse code template

Cumartesi, 15 Eki 2011 Yorum yapılmamış

Eclipse’in bir güzel özelliği de sık kullanılan kimi kod blokları, şablonları için kısayol oluşturabiliyor olmak. Tıpkı “syso” yazıp Ctrl+Space yapınca “System.out.println();” satırını veya “main” yazıp sınıfa bir main metodu eklemek gibi.

Bunun için yapılması gereken Window->Preferences->Java->Editor->Templates kısmından yeni bir şablon eklemek. Mesela ben debug yaparken işlemi yarıda kesmek istediğim zaman kullandığım kod bloğu olan throw new RuntimeException(“Hata !”); ifadesini “throws” kısayolu ile eşledim. Çok da güzel oldu, iyi de oldu : )

Eclipse Code Template

Eclipse’in yine kod şablonları oluşturabilmek için “Snippets” görünümü de bulunuyor. Ctrl+3 ile açılan görünüm seçiçiden “Snippets” yazılarak benzer şekilde kod şablonları oluşturulabilir.

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

Hibernate dynamic-insert, dynamic-update

Cumartesi, 06 Ağu 2011 Yorum yapılmamış

Hibernate’in bir kullanılabilir özelliği daha; dynamic-insert, dynamic-update : )

dynamic-update : Güncelleme sql ifadesini(update sql) çalışma zamanında sadece değişen kolonlara göre dinamik olarak oluşturur.
dynamic-insert : Kayıt ekleme sql ifadesini(insert sql) çalışma zamanında sadece veri girilmiş kolonlara göre dinamik olarak oluşturur.

Şöyle ki;

@Entity
@Table(name = "PERSONEL")
@org.hibernate.annotations.Entity(dynamicInsert=true,dynamicUpdate=true)
public class PERSONEL{
...
...
...
}

Sadece AD, SOYAD ve TC_KIMLIK_NO alanlarının girildiği bir kayıt işlemi sonrası

INSERT INTO PERSONEL(AD, SOYAD, PERSONEL_NO, TC_KIMLIK_NO, YAS, CINSIYET, DOGUM_TARIHI)  VALUES (?, ?, ?, ?, ?, ?, ?)

gibi bir sql ifadesi oluşması yerine

INSERT INTO PERSONEL(AD, SOYAD, TC_KIMLIK_NO)  VALUES (?, ?, ?)

gibi sadece veri girilmiş alanların dahil edildiği bir sql ifadesi oluşuyor.

Performans açısından ise şöyle bir ters orantı var. Normal koşullarda Hibernate her varlık sınıfı için üretilen ekleme , güncelleme, sorgulama sql ifadelerini belleğine alır. Böylece her ekleme, güncelleme, sorgulama işlemi için bir sql ifadesi oluşturması gerekmez. Bu performans açısından bir artı getirir. Amma lakin ki bu özellik aktif hale getirildiğinde de her ekleme, güncelleme işlemi için bir sql ifadesi oluşturma işi çıkıyor ortaya. Dolayısıyla çok fazla kolon içeren tablolar için çalıştırılacak sql ifadesini minumuma indirerek performans açısından bir artı getirebilse de diğer durumlar için karar vermek gerekiyor, bu özelliği aktif yapıp yapmamaya.

FacebooktwitterlinkedinmailFacebooktwitterlinkedinmail

Hibernate @SqlDelete

Cumartesi, 06 Ağu 2011 Yorum yapılmamış

Hibernate’in yeni keşfettiğim bir özelliği varlık sınıflarına uygulanabilen @SqlDelete, @SqlUpdate, @SqlInsert bildirimleri. Bu sayede ilgili varlık sınıflarını kaydetme, güncelleme ve silme işlemleri sırasında hangi sql ifadesinin çalışacağını belirleyebiliyoruz. Bir nevi EntityManager sınıfının persist, merge ve remove metotları sonucu oluşacak olan ekleme, güncelleme ve silme sql ifadelerini ezmiş oluyoruz. Özellikle silme işlemi için oldukça faydalı olabilir diye düşündüm.

Mesela; Hesap nesnelerini karşılayan Hesap sınıfları için ne zaman entityManager.remove(herhangiBirHesap) desek, bu nesneyi fiziksel olarak silmek yerine mantıksal olarak durumunu pasif yapmak isteyebiliriz. “Soft delete” olarak bilinen durum yani. Bu gibi durumlar için proje genelinde bir kod tasarrufu ve temizliği sağlanabilir gibi.

Ayrıca sınıf tanımında kullanılacak @Where bildirimi ile de veritabanından Hesap tablosuna sorgu atan sql ifadelerine bir koşul konulabiliyor. Böylece de durumunu pasif yaptığımız nesneler sorgu sonuçlarında gelmiyor. Bu yazılan sql ifadeleri için hql kullanılamıyor bu arada, sql yazmak gerekiyor.

Şöyle ki;

@Entity
@Table(name = “HESAP”)
@SQLDelete(sql=”update HESAP set DURUM=0 WHERE ID=?”)
@Where(clause=”DURUM <>0″)
public class Hesap {



}

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