Dizi algoritmaları ve ArrayList
Doğrusal arama, sayma, yerinde ters çevirme, gerçek kopya ile takma ad farkı, kaydırma ve sıralı mı kontrolü; ardından boyutu değişen liste ArrayList ve metotları. Sınavda hem iz sürme hem kısa metot yazma olarak gelir.
Diziyi oluşturmayı ve gezmeyi biliyorsun. Bu hafta onunla yapılan standart işler var: arama, sayma, ters çevirme, kopyalama, kaydırma. Hepsi birkaç satırlık kalıplar ve sınavda “write a method” sorusu olarak tekrar tekrar gelir. İkinci yarıda dizinin boyut sorununu çözen ArrayList’i öğreneceksin.
Altın kurallar:
- Arama bulunca hemen return eder, bulamazsa döngüden sonra -1.
- Yerinde ters çevirmede döngü yarıya kadar gider:
i < length / 2. b = akopya değildir. Kopya için yeni dizi aç.- ArrayList’te boyut
size(), elemanget(i). Köşeli parantez yok. - Döngüde eleman siliyorsan sondan başa git.
Doğrusal arama ve sayma
public static int linearSearch(int[] arr, int key) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == key) return i; // bulduk, hemen çık
}
return -1; // hiç bulunmadı
}
public static int count(int[] arr, int key) {
int c = 0;
for (int x : arr) if (x == key) c++;
return c;
}
// main içinde:
int[] a = {8, 3, 5, 3, 1};
System.out.println(linearSearch(a, 3) + " " + linearSearch(a, 1) + " " + linearSearch(a, 7));
System.out.println(count(a, 3));
1 4 -1
2
-1 geçerli bir indeks olmadığı için “bulunamadı” anlamında kullanılır. return -1 satırı döngünün dışında olmalı. İçeride bir else’e koyarsan sadece ilk elemanı kontrol etmiş olursun.
Yerinde ters çevirme
Baştaki ile sondakini takas et, sonra ikinci ile sondan ikinciyi, ortaya kadar.
public static void reverse(int[] arr) {
for (int i = 0; i < arr.length / 2; i++) {
int temp = arr[i];
arr[i] = arr[arr.length - 1 - i];
arr[arr.length - 1 - i] = temp;
}
}
{1, 2, 3, 4, 5} ve {1, 2, 3, 4} için:
[5, 4, 3, 2, 1]
[4, 3, 2, 1]
i takas edilen indeksler dizi (5 eleman)
0 0 ↔ 4 [5, 2, 3, 4, 1]
1 1 ↔ 3 [5, 4, 3, 2, 1]
2 döngü biter (2 < 5/2 = 2 false), ortadaki 3 yerinde kalır
TUZAK · sonuna kadar gitmek. Döngüyü
i < arr.lengthyaparsan ilk yarıda ters çevirir, ikinci yarıda geri çevirirsin. Doğrulamada bu sürüm diziyi[1, 2, 3, 4, 5]olarak, yani hiç değişmemiş bıraktı.
Kopya ve takma ad (alias)
int[] orig = {1, 2, 3};
int[] alias = orig; // aynı dizi
int[] real = copy(orig); // döngüyle kopya
int[] c2 = Arrays.copyOf(orig, orig.length); // hazır kopya
orig[0] = 99;
System.out.println(alias[0] + " " + real[0] + " " + c2[0]);
System.out.println((orig == alias) + " " + (orig == real));
int[] x1 = {1, 2}, x2 = {1, 2};
System.out.println((x1 == x2) + " " + Arrays.equals(x1, x2));
99 1 1
true false
false true
Döngüyle kopya şöyle yazılır:
public static int[] copy(int[] arr) {
int[] result = new int[arr.length];
for (int i = 0; i < arr.length; i++) result[i] = arr[i];
return result;
}
== dizilerde içeriğe bakmaz, iki değişkenin aynı diziyi gösterip göstermediğine bakar. İçerik karşılaştırması için Arrays.equals (ya da kendi döngün).
Sıralı mı? Kaydırma. Sıralama.
public static boolean isSorted(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) { // i+1'i kullandığımız için length-1
if (arr[i] > arr[i + 1]) return false;
}
return true;
}
public static void shiftLeft(int[] arr) { // sola döndür
int first = arr[0];
for (int i = 0; i < arr.length - 1; i++) arr[i] = arr[i + 1];
arr[arr.length - 1] = first;
}
isSorted({1, 3, 3, 7}), isSorted({1, 5, 2}), shiftLeft({10, 20, 30, 40}) ve Arrays.sort({5, 2, 9, 1}):
true false
[20, 30, 40, 10]
[1, 2, 5, 9]
İPUCU ·
i + 1görürsen sınırı düşür. Döngüdearr[i + 1]kullanıyorsan son turi = length - 2olmalı, yoksa son turda dizinin dışına çıkarsın. Koşuli < arr.length - 1.
ArrayList: boyutu değişen dizi
Dizinin boyutu baştan sabittir. Kaç eleman geleceğini bilmiyorsan (kullanıcı -1 girene kadar sayı oku, listeden eleman sil) ArrayList kullanırsın. Kendisi büyür ve küçülür.
import java.util.ArrayList;
ArrayList<String> names = new ArrayList<>();
names.add("Ali");
names.add("Can");
names.add("Ece");
System.out.println(names + " " + names.size());
names.add(1, "Bora"); // 1. indekse ekle, gerisi kayar
System.out.println(names);
System.out.println(names.get(2));
names.set(0, "Arda"); // değiştir
System.out.println(names);
names.remove(3); // indeksle sil
System.out.println(names);
names.remove("Bora"); // değerle sil
System.out.println(names);
System.out.println(names.contains("Can") + " " + names.indexOf("Can") + " " + names.indexOf("Zeynep"));
System.out.println(names.isEmpty());
[Ali, Can, Ece] 3
[Ali, Bora, Can, Ece]
Can
[Arda, Bora, Can, Ece]
[Arda, Bora, Can]
[Arda, Can]
true 1 -1
false
| Dizi | ArrayList | Ne yapar |
|---|---|---|
new int[5] | new ArrayList<Integer>() | oluştur |
a.length | list.size() | eleman sayısı |
a[i] | list.get(i) | oku |
a[i] = x | list.set(i, x) | değiştir |
| (yok) | list.add(x), list.add(i, x) | ekle |
| (yok) | list.remove(i), list.remove(x) | sil |
| döngüyle ara | list.contains(x), list.indexOf(x) | ara |
Geçersiz indeksle get çağırırsan çöker: IndexOutOfBoundsException: Index 1 out of bounds for length 1.
Wrapper sınıflar ve autoboxing
ArrayList sadece nesne tutar, primitive tutamaz. ArrayList<int> derlenmez (unexpected type). Her primitive’in bir sarmalayıcı (wrapper) sınıfı var: int → Integer, double → Double, char → Character, boolean → Boolean. Java aralarındaki dönüşümü kendisi yapar (autoboxing / unboxing):
ArrayList<Integer> nums = new ArrayList<>();
for (int i = 1; i <= 5; i++) nums.add(i * 10); // int → Integer otomatik
System.out.println(nums);
nums.remove(1); // İNDEKS 1
System.out.println(nums);
nums.remove(Integer.valueOf(40)); // DEĞER 40
System.out.println(nums);
int first = nums.get(0); // Integer → int otomatik
System.out.println(first + 1);
for (int i = 0; i < nums.size(); i++) System.out.print(nums.get(i) + " ");
[10, 20, 30, 40, 50]
[10, 30, 40, 50]
[10, 30, 50]
11
10 30 50
TUZAK ·
remove(1)miremove(değer)mi? Integer listesinderemove(1)int argüman aldığı için indeks 1’i siler. 1 değerini silmek istiyorsanremove(Integer.valueOf(1))yaz. String listesinde karışıklık yok:remove("Bora")değeri siler.
Döngüde silme
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(2, 4, 5, 6, 7));
for (int i = 0; i < list.size(); i++) {
if (list.get(i) % 2 == 0) list.remove(i); // baştan: HATALI
}
System.out.println(list);
ArrayList<Integer> list2 = new ArrayList<>(Arrays.asList(2, 4, 5, 6, 7));
for (int i = list2.size() - 1; i >= 0; i--) {
if (list2.get(i) % 2 == 0) list2.remove(i); // sondan: DOĞRU
}
System.out.println(list2);
[4, 5, 7]
[5, 7]
Baştan giderken 2 silinince 4 sıfırıncı indekse kaydı, ama i 1’e geçtiği için 4 hiç kontrol edilmedi. Sondan gidersen silinen elemanın sağı zaten kontrol edilmiş olur.
Sık yapılan hatalar
| Yanlış düşünce | Doğrusu |
|---|---|
return -1 döngünün içinde else’te | Döngüden sonra |
Ters çevirme döngüsü i < length | i < length / 2, yoksa geri döner |
int[] b = a; kopya | Aynı dizi; Arrays.copyOf ya da döngü |
a == b içerik karşılaştırır | Referans; Arrays.equals |
arr[i + 1] ile i < length | i < length - 1 |
ArrayList<int> | ArrayList<Integer> |
list.length, list[i] | list.size(), list.get(i) |
list.set(i, x) ekleme yapar | Yerine koyar; boyut değişmez |
Integer listesinde remove(5) 5’i siler | 5. indeksi siler |
| Baştan giderek silmek güvenli | Eleman atlanır; sondan gez |
Kendini test et
Sınavdaki gibi İngilizce sorular. Önce kâğıt kalemle çöz, sonra cevabı aç.
Using linearSearch (returns the first index of key, or -1) and count (returns how many times key appears), what is printed?
int[] a = {4, 7, 4, 2, 4};
System.out.println(linearSearch(a, 4) + " " + count(a, 4) + " " + linearSearch(a, 9));Cevabı göster
linearSearch ilk eşleşmede return eder: indeks 0. count tüm diziyi gezer: 4 üç kez var. 9 hiç yok: -1.
What is printed?
int[] a = {1, 2, 3, 4, 5, 6};
for (int i = 0; i < a.length / 2; i++) {
int t = a[i];
a[i] = a[a.length - 1 - i];
a[a.length - 1 - i] = t;
}
System.out.println(a[0] + " " + a[2] + " " + a[5]);Cevabı göster
Yerinde ters çevirme (reverse in place): i = 0, 1, 2 için baştaki ve sondaki eşi takas edilir. Dizi {6, 5, 4, 3, 2, 1} olur. a[0] = 6, a[2] = 4, a[5] = 1.
What is printed?
int[] a = {3, 6, 9};
int[] b = a;
int[] c = Arrays.copyOf(a, 3);
b[0] = 0;
c[1] = 0;
System.out.println(a[0] + " " + a[1]);Cevabı göster
b, a ile aynı diziyi gösterir (alias); b[0] = 0 a'yı da değiştirir. c gerçek bir kopya, ayrı bir dizi; c[1] = 0 a'ya dokunmaz.
What is printed?
int[] a = {1, 2, 3, 4, 5};
for (int i = 0; i < a.length - 1; i++) a[i] = a[i + 1];
System.out.println(Arrays.toString(a));Cevabı göster
Her eleman sağındakini alır: sola kaydırma. Son eleman yerinde kalır (döngü length - 1'de durur), 5 iki kez görünür. İlk eleman (1) kayboldu; döndürme (rotate) isteseydin onu baştan saklayıp sona koyardın.
What is printed?
ArrayList<String> list = new ArrayList<>();
list.add("x");
list.add("y");
list.add(0, "z");
list.add("w");
list.set(2, "v");
System.out.println(list + " " + list.size());Cevabı göster
add sona ekler: [x, y]. add(0, "z") başa ekler, diğerlerini kaydırır: [z, x, y]. Sona w: [z, x, y, w]. set(2, "v") 2. indeksteki y'nin yerine v koyar (boyut değişmez).
What is printed?
ArrayList<Integer> list = new ArrayList<>();
list.add(5); list.add(10); list.add(15); list.add(20);
list.remove(1);
list.remove(Integer.valueOf(20));
System.out.println(list);Cevabı göster
remove(1) int argümanla indeks 1'i siler (10). remove(Integer.valueOf(20)) nesne argümanla değeri 20 olan elemanı siler. Integer listelerinde bu fark klasik bir tuzak.
What is printed?
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(3, 3, 3, 8));
for (int i = 0; i < list.size(); i++) {
if (list.get(i) == 3) list.remove(i);
}
System.out.println(list);Cevabı göster
i = 0: 3 silinir, liste [3, 3, 8] olur ve elemanlar sola kayar. i = 1: get(1) = 3, silinir: [3, 8]. i = 2: 2 < 2 false, döngü biter. Baştaki 3 atlandı, çünkü silme sonrası kayan eleman kontrol edilmedi. Çözüm: sondan başa doğru gez.
What is printed?
ArrayList<String> list = new ArrayList<>(Arrays.asList("cat", "dog", "cow"));
int total = 0;
for (String s : list) if (s.startsWith("c")) total += s.length();
System.out.println(total + " " + list.indexOf("cow") + " " + list.contains("Dog"));Cevabı göster
c ile başlayanlar cat ve cow: 3 + 3 = 6. cow 2. indekste. contains equals ile arar ve büyük/küçük harfe duyarlıdır: "Dog" yok.
Using isSorted (returns true if every element is <= the next one), what is printed?
int[] a = {2, 8, 5};
System.out.println(isSorted(a));
Arrays.sort(a);
System.out.println(isSorted(a) + " " + a[1]);Cevabı göster
true 5
8 > 5 olduğu için ilk kontrol false. Arrays.sort diziyi küçükten büyüğe yerinde sıralar: {2, 5, 8}. Artık sıralı, ortadaki eleman 5.
What is printed?
int[] a = {1, 2, 3};
int[] b = {1, 2, 3};
System.out.println((a == b) + " " + Arrays.equals(a, b));Cevabı göster
== iki referansın aynı diziyi gösterip göstermediğine bakar; a ve b iki ayrı dizi. Arrays.equals eleman eleman karşılaştırır.
Write a static method reversedCopy(int[] arr) that returns a NEW array with the elements in reverse order and leaves arr unchanged.
Cevabı göster
Yeni dizi aynı boyutta açılır. i. eleman, orijinalin sondan i. elemanıdır.public static int[] reversedCopy(int[] arr) { int[] result = new int[arr.length]; for (int i = 0; i < arr.length; i++) { result[i] = arr[arr.length - 1 - i]; } return result;}Test: {1, 2, 3, 4} → arr hâlâ [1, 2, 3, 4], sonuç [4, 3, 2, 1].
Write a static method removeNegatives(ArrayList<Integer> list) that removes every negative number from the list.
Cevabı göster
Sondan başa gezersen bir eleman silindiğinde kayan elemanlar zaten kontrol edilmiş olur; hiçbir şey atlanmaz.public static void removeNegatives(ArrayList<Integer> list) { for (int i = list.size() - 1; i >= 0; i--) { if (list.get(i) < 0) list.remove(i); }}Test: [-1, -2, 5, -3, 4, -6] → [5, 4]. Baştan gezip silseydin ardışık negatiflerden biri atlanırdı.
Doğrulama: Tüm çıktılar JDK 26 ile çalıştırıldı (verify/SEN1001/W07.java ve W07b.java). ArrayList<int> derleme hatası verify/SEN1001/err/Prim.java, get sınır hatası err/Get.java ile alındı.