Pure Java – 72 Generics & Collections – Set

Merhaba Arkadaslar,
Bu yazida Java Collection API’de bulunan java.util.Set konusunu dolayisiyla java.util.HashSet , java.util.LinkedHashSet ve java.util.TreeSet siniflarini inceleyecegiz. Hatirlayacagimiz gibi java.util.Set bir arabirimdir ve java.util.Collection arabirimini kalitmaktadir.

public interface Set<E> extends Collection<E> { .. }

Matematikte bir kumede(set) ayni elamandan sadece birtane olabilir. Benzer sekilde Java’da da Set mantiginda duplicate elamanlara izin verilmez. Set’e eleman eklemek icin List’te oldugu gibi add metodunu kullanabiliriz. List orneklerinde kullandigimiz metotlar isEmpty , size , contains , remove , clear gibi metotlari kullanabiliriz.

import java.util.HashSet;
import java.util.Set;

public class HashSetExample {

	public static void main(String[] args) {
		Set<Integer> numbers = new HashSet<Integer>();

		boolean isEmpty = numbers.isEmpty();
		int size = numbers.size();

		System.out.println("isEmpty:" + isEmpty);
		System.out.println("size:" + size);

		numbers.add(5);
		numbers.add(5);
		// Ayni int degerini 2 kere eklemeye izin vermez.
		numbers.add(10);
		numbers.add(25);
		numbers.add(100);
		numbers.add(500);
		numbers.add(1000);

		isEmpty = numbers.isEmpty();
		size = numbers.size();
		boolean contains = numbers.contains(5);
		boolean remove = numbers.remove(25);
		System.out.println("isEmpty:" + isEmpty);
		System.out.println("size:" + size);
		System.out.println("contains:" + contains);
		System.out.println("remove:" + remove);

		for (Integer number : numbers) {
			System.out.println(number);
		}

		Set<String> names = new HashSet<String>();
		names.add("names1");
		names.add("names2");
		names.add("names3");
		names.add("names4");
		names.add("names4");
		names.add(new String("names4"));
		// ayni String degeri eklememize izin vermez.

		for (String name : names) {
			System.out.println(name);
		}
	}
}

Set’in elemanlarini dondurmek icin gelismis for dongusu veya Iterator sinifini kullanabiliriz.

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class IteratorSet {

	public static void main(String[] args) {
		Set<Integer> numbers = new HashSet<Integer>();
		numbers.add(10);
		numbers.add(25);
		numbers.add(100);
		numbers.add(500);
		numbers.add(1000);

		for (int i : numbers) {
			System.out.println(i);
		}

		System.out.println();
		Iterator iterator = numbers.iterator();
		while (iterator.hasNext()) {
			System.out.println(iterator.next());
		}

	}

}

HashSet’ icin dikkat edecegimiz 2 nokta ;

  • Duplicate eleman eklemeye izin vermez.
  • Eleman eklenmesi List’te oldugu gibi index based degildir. Elemanlari ekledigimiz sirada HashSet’e eklenmez.(Unordered)

Eger ordered bir Set veri yapisina ihtiyacimiz varsa LinkedHashSet kullanabiliriz.

import java.util.LinkedHashSet;
import java.util.Set;

public class LinkedHashSetExample {

	public static void main(String[] args) {
		Set<Integer> numbers = new LinkedHashSet<Integer>();

		numbers.add(5);
		numbers.add(5);
		// Ayni int degerini 2 kere eklemeye izin vermez.
		numbers.add(10);
		numbers.add(25);
		numbers.add(100);
		numbers.add(500);
		numbers.add(1000);

		for (Integer number : numbers) {
			System.out.println(number);
		}

		Set<String> names = new LinkedHashSet<String>();
		names.add("names1");
		names.add("names2");
		names.add("names3");
		names.add("names4");
		names.add("names4");
		names.add(new String("names4"));
		// ayni String degeri eklememize izin vermez.

		for (String name : names) {
			System.out.println(name);
		}
	}
}

List orneklerimizde toArray metotu ile Set’i array/diziye donusturebiliriz.

import java.util.LinkedHashSet;
import java.util.Set;

public class ToArrayMethod {

	public static void main(String[] args) {
		Set<String> names = new LinkedHashSet<String>();
		names.add("names1");
		names.add("names2");
		names.add("names3");
		names.add("names4");
		names.add("names4");

		Object[] objectArray = new Object[names.size()];
		objectArray = names.toArray();

		for (Object o : objectArray) {
			System.out.println(o);
		}
		System.out.println();
		
		String[] myArray = new String[names.size()];
		names.toArray(myArray);
		
		for (String name : myArray) {
			System.out.println(name);
		}
		
	}
}

Arrays.asList metodunu onceki bolumlerde kullandik. Arrays.asSet metodu yok, bir diziyi Set’e cevirmek icin overloaded yapilandirici yardimi ile kullanabiliriz.

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class ArrayToSet {
	public static void main(String[] args) {
		String[] names = { "name1", "name2", "name3", "name4", "name5" };

		Set<String> mySet = new HashSet<String>(Arrays.asList(names));
		mySet.add("name6");

		for (String name : mySet) {
			System.out.println(name);
		}
	}
}

Simdi de String veya Wrapper sinif disinda bir ornek inceleyelim ;

import java.util.HashSet;
import java.util.Set;

class Car {

}

public class HashSetTest {
	public static void main(String[] args) {
		Car car = new Car();
		Car car2 = new Car();
		Car car3 = new Car();

		Set<Car> carSet = new HashSet<Car>();
		carSet.add(car);
		carSet.add(car2);
		carSet.add(car3);

		System.out.println(carSet.size());
	}
}

Bu ornekte 3 elemani da HashSet’e ekleyecektir. Bu referans degiskenleri icin equals metodu false dondugu icin bunlarin hic biri duplicate eleman durumunda degildir. Dolayisiyla elemanlar diziye eklenir. equals metodunu override ettigimiz durumda ise equals true olan referans degiskenleri icin duplicate durumu soz konusudur.

import java.util.HashSet;
import java.util.Set;

class Car {
	String hp;
	String brand;
	Integer price;

	public Car(String hp, String brand, Integer price) {
		super();
		this.hp = hp;
		this.brand = brand;
		this.price = price;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((brand == null) ? 0 : brand.hashCode());
		result = prime * result + ((hp == null) ? 0 : hp.hashCode());
		result = prime * result + ((price == null) ? 0 : price.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Car other = (Car) obj;
		if (brand == null) {
			if (other.brand != null)
				return false;
		} else if (!brand.equals(other.brand))
			return false;
		if (hp == null) {
			if (other.hp != null)
				return false;
		} else if (!hp.equals(other.hp))
			return false;
		if (price == null) {
			if (other.price != null)
				return false;
		} else if (!price.equals(other.price))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "Car [hp=" + hp + ", brand=" + brand + ", price=" + price + "]";
	}

}

public class HashSetTest {
	public static void main(String[] args) {
		Car car = new Car("100HP", "Ford", 1000);
		Car car2 = new Car("100HP", "Ford", 1000);
		// car.equals(car2) true donecektir. Dolayisiyla duplicate olacaktir.

		// car car3 car4 arasinda equals false oldugu icin Set'e duplicate
		// olmadan eklenir.
		Car car3 = new Car("50HP", "Fiat", 1000);
		Car car4 = new Car("10HP", "Ford", 100);

		Set<Car> carSet = new HashSet<Car>();
		carSet.add(car);
		carSet.add(car2);
		carSet.add(car3);
		carSet.add(car4);

		System.out.println(carSet.size());

		for (Car c : carSet) {
			System.out.println(c);
		}
	}
}

Son olarak ordered ve sorted ozellige sahip olan java.util.TreeSet’i inceleyelim. Hatirlayacagimiz gibi Collection’lari Generics olmadan da kullanabiliriz. TreeSet eger Generics yapida tanimlanmadiysa ilk hangi tipte eleman eklendiyse sonraki elemanlar da ayni tipte olmalidir. Bu durum HashMap, LinkedHashMap , ArrayList vs icin gecerli degildir.
Bunun nedeni TreeSet sorted oldugu icin farkli tipteki elemanlari siralama yapamayacaktir.

import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;

public class TreeSetTest {

	public static void main(String[] args) {

		Set linkedHashSet = new LinkedHashSet();
		linkedHashSet.add(10);
		linkedHashSet.add(20);
		linkedHashSet.add("non-generic durumda string de ekleyebiliriz.");

		Set treeSet = new TreeSet();

		treeSet.add(10);
		treeSet.add(20);
		// TreeSet e Integer elemanlar ekledikten sonra String ekleyemeyiz.
		treeSet.add("ClassCastException");
		// java.lang.ClassCastException: java.lang.Integer cannot be cast to
		// java.lang.String
	}
}

Bir diger ornegimizi inceleyelim , TreeSet’e Car tipinde eleman ekleyelim ;

import java.util.Set;
import java.util.TreeSet;

class Car {
}

public class TreeSetTest2 {
	public static void main(String[] args) {
		Set treeSetCar = new TreeSet();

		Car car = new Car();

		treeSetCar.add(car);
		// Car sinifi Comparable olmadigi icin calisma zamaninda
		// java.lang.ClassCastException hatasi verecektir.
	}
}

Car sinifi Comparable olmadigi icin calisma zamaninda java.lang.ClassCastException hatasi verecektir. Peki neden Integer ya da String tipinde eleman ekledigimizde calisma zamaninda hata almiyoruz ?
Bunun nedeni Wrapper siniflar ve String Comparable arabirimini uygulamaktadir.

public final class Integer extends Number implements Comparable { ..}
public final class String
    implements java.io.Serializable, Comparable, CharSequence {

Car sinifimiz icin java.util.Comparable arabirimini uygulayalim.Bu durumda TreeSet’e Car tipinde elemanlar ekleyebiliriz.

import java.util.Set;
import java.util.TreeSet;

class Car implements Comparable {

	public Car(String hp, String brand, Integer price) {
		super();
		this.hp = hp;
		this.brand = brand;
		this.price = price;
	}

	private String hp;
	private String brand;
	private Integer price;

	@Override
	public int compareTo(Car car) {
		return price.compareTo(car.price);
	}

	@Override
	public String toString() {
		return "Car [hp=" + hp + ", brand=" + brand + ", price=" + price + "]";
	}
}

public class TreeSetTest3 {

	public static void main(String[] args) {
		Car ford = new Car("50", "ford", 100);
		Car fiat = new Car("20", "fiat", 50);
		Car subaru = new Car("500", "subaru", 5000);
		Car bmw = new Car("200", "bmv", 1000);

		Set treeSetCar = new TreeSet();
		treeSetCar.add(ford);
		treeSetCar.add(fiat);
		treeSetCar.add(subaru);
		treeSetCar.add(bmw);

		for (Car c : treeSetCar) {
			System.out.println(c);
		}

	}
}

Yazimi burada sonlandiriyorum.
Herkese Bol Javali Gunler dilerim.
Be an oracle man , import java.*;
Levent Erguder
OCP, Java SE 6 Programmer
OCE, Java EE 6 Web Component Developer

Print Friendly, PDF & Email

Leave a Reply

Your email address will not be published. Required fields are marked *