Neden okullar Listedeki dizileri öğretiyor? [kapalı]


36

Okulumdaki ilk programlama dersleri için yapılan ödevlerin çoğu, dizileri kullanmamı gerektiriyordu. Şimdi tam gün çalışıyorum ve üzerinde çalıştığım herhangi bir proje için hiçbir zaman bir dizi kullanmadım. Mevcut projelerde bile, dizilerin kullanımını hiçbir yerde görmedim. Bence List kullanımı daha kolay ve standart. Neden profesörler öğrencilere ödevlerinde dizileri kullanmalarını söylüyor? Sadece öğrencilerin temelleri anlamaları için mi?

Üniversitelerin çoğu Java öğrettiğinden, bu soru Java'ya özgüdür.


7
Diziler daha temeldir.
user253751

Yorumlar uzun tartışmalar için değildir; bu konuşma sohbete taşındı .
Dünya Mühendisi

Yanıtlar:


120

Diziler dizin oluşturma ve sınırlama gibi kavramları öğrettiğinden, bilgisayar programlamasında temelde iki önemli kavram vardır.

Listeler "standart" değildir . Dizilerin mükemmel bir uyum sağladığı çok çeşitli problem alanları vardır.


Yorumlar uzun tartışmalar için değildir; bu konuşma sohbete taşındı .
Dünya Mühendisi

48

Muhtemelen bir bilgisayarın nasıl çalıştığını en doğru şekilde temsil eden veri yapısıyla başlamak istediler, bu yüzden çalışmayı kolaylaştıran Listeler gibi üst düzey soyutlamalar yapmaya başlamadan önce temelleri biliyorsunuzdur. Aksi halde, bazı işlemler için belirli bir yapının veya algoritmanın neden bazı işlemler için yavaş / hızlı olduğunu anlama imkanınız olmaz; Bilgisayar hafızası aslında bağlı listelerden yapılmış olsaydı, dünya çok farklı bir yer olurdu.

Aynı sebepten ötürü, kolejdeki ilk programlama dersim C'deydi ve derslerin tamamı C ++, Java ve diğer dillerdeydi. C bir şekilde daha iyi ya da daha kolay değil, C (ve Dizi) senden hiçbir şey gizlemiyor.


7
Bir liste gerçek kodla çalışmak daha kolaydır, ancak bir dizinin (tamamen) anlaşılması daha kolaydır ve temel ve evrensel oldukları için anlaşılması daha kolaydır (Java'nın Listesi) değildir. En azından benim fikrim bu.
Ixrec 11:15,

21
İçindeki bir dizide sakladığınız ve daha sonra erişeceğiniz bir atama bir veri yapısı atamasıdır . Sadece farketmemiş olabilirsin. Kendine sormalısın, daha iyi mühendisler üreten, temel hesaplama modellerini anlayan veya bir dilin standart kütüphanesini mi öğreniyorsun? Genel fikir birliği (ve katılıyorum, fwiw), önce hesaplama temellerini anlamadan kütüphane içeriğinin çoğunu anlayamayacağınızdır.
Kent A.

12
LinkedList, ArrayList, OrderedList, vb. Önce hangi listeyi öğrenmelisiniz? Neden ilk başta olduklarını anlamadıysanız, sizin için neler yaptıklarını nasıl takdir edersiniz?
Kent A.

10
+1 ila @KentAnderson. Okullar veri yapılarını düşük seviyede anlayan mühendisler üretmelidir; İdeal olarak, C'deki temel yapıları kolayca uygulayabilen mühendisler üretmek. Başka bir program yalnızca bir Java okulu.
Christian Willman

2
“Muhtemelen bir bilgisayarın nasıl çalıştığını en doğru şekilde temsil eden veri yapısıyla başlamak istediler” - Peki, liste yapılı veya nesne yapılı hafızalı bilgisayarlar? “C bir şekilde daha iyi ya da daha kolay değil, C (ve Array) senden hiçbir şey gizlemiyor.” - Bilgisayarınızda işaretçiler yoksa, AS / 400 gibi, C aslında bir VM'de çalışır ve sizin için hemen hemen her şeyi gizler .
Jörg W Mittag

21

Yukarıdaki cevaplar harika, ama başka aklımda var. Java'nın main()yöntemi, öğrencilerin, sınıfın ilk günü olduğu gibi, çok erken saatlerde temel dizilerle karşılaştıkları anlamına gelir. Neden?

public static void main(String[] args)

Hello World ve ötesi yazmak için uğraşmanız gereken ilk şey bu. (Bazı kursların başlangıçta BlueJ gibi IDE öğretimi kullandığını gördüm, bu da keyfi yöntemleri çalıştırmak için tıkla ve tıklatmanıza izin veriyor, ancak bunları bir kenara koyacağız…) bu anahtar kelimeleri kısa bir süre için, er ya da geç çoğu öğretmen bunları açıklamak isteyecektir. Gerçekten de, başlangıç ​​seviyesindeki klasik bir test sorusu, öğrencilerden temel bir Hello World programında her bir anahtar kelimenin anlamını vermelerini istemektir. Ve ana yöntem imzamızın bir parçası olarak ne buluyoruz? Bir dizi (Bunun nedeni, kısmen tarihseldir. ArrayList, Java 1.0'da mevcut değildi). Diziler, bu temel bilgi kümesinin bir parçasıdır. Liste değil.

Bununla birlikte, derslerin ArrayList'i kursu bir süre sonra tanıtması, özellikle nesneler ve kullanımları ele alındıktan sonra, nadir değildir. Java için AP Bilgisayar Bilimi müfredatı bile ArrayList'i içeriyor (ben bunu biliyorum ve Google hala yaptığını gösteriyor gibi görünüyor), ancak ArrayList'in List'i ve Koleksiyonlar Çerçevesinin geri kalanını uyguladığını görmezden geliyor.

Son olarak, üniversite CS programlarının Java'yı CS'yi ve programlama kavramlarını araştırmak için bir araç olarak kullanması, öğrencilere nasıl iyi Java geliştiricileri olunacağını öğretmek benim deneyimim. Bazı programlar profesyonel geliştiricileri çalkalamaya odaklanırken, diğerleri teoriye odaklanırken, her iki durumda da, çoğu üniversite müfredatında öğretilmeyen gerçek profesyonel çalışmalarda Java'nın nasıl kullanılacağı hakkında çok şey öğrenilebilir. Bu, Etkili Java'dakiler gibi tasarım desenlerinden ve tekniklerinden Spring, Hibernate veya JUnit gibi çerçevelere veya JSP veya JDBC gibi daha yaygın şeylere kadar uzanır. Bu felsefeyle, daha yaygın olarak kullanılan ArrayList'in dizilerine vurgu yapmak biraz daha mantıklı geliyor.


3
@Deduplicator emin. Sadece dizilerle ilgili olan noktamla ilgili değildi, bu yüzden bunu ihmal ettim. Ayrıca System.out.println'yi ("Merhaba Dünya!") Eklemedim; Ya.
Zach Lipton

“Gerçek dünya” için etkili teknikler ve kavramlar için +1 Hiç kimse sürüm kontrolünü öğretmiyordu, en azından okuldayken - ama o zaman ben
David

Zamanlayıcı gibi çeşitli parçaları uygulamak zorunda olduğumuz bir işletim sistemi dersi aldım; bir seferde böyle bir parçaya odaklandık (özel olarak) çünkü o noktada daha fazlasını yapamadık . Ancak , aynı anda çalışarak bu parçaların hepsini almaya çalışmayı düşünmek , bana (başlangıçlarda) "gerçek dünya" geliştirme / "genel olarak programlama" nın karmaşıklıklarının takdir edilmesini sağladı.
David,

14

Birinci sınıf programlama sınıflarının dizileri kullanmasının bir nedeni mirastır: Profesörler, önceden hazırlanmış dinamik listeleri olan standart kütüphaneleri kullanmaya başlamadan önce bunu ilk öğrendiler. İlkel veri türlerini kullanmak daha genel olarak uygulanabilir: diziler hemen hemen her bilgisayarda var. güneşin altında bir dil (ve bir avuç montaj talimatıyla uygulanabilir). Programlamayı ilk öğrenirken, bağlantılı bir listeyi uygulamak ödevlerden biriydi.

İlk ilkelerden başlamak ve daha sonra "Bu temel yapı. Bu dil (veya kütüphaneleri) size tüm bunları yapan, ancak x, y ve z 'yi veren" veri yapısını verir. "Yani bu, bu üst düzey veri yapıları, işte şimdi başlık altında olan şey." LinkedList'e karşı ArrayList (veya HashSet'e karşı bir TreeSet) kullanıp kullanmamayı öğrenmek, genellikle ikinci veya üçüncü sınıf bir Algoritma dersidir. Listeler ve Haritalar aynı arayüzlere sahip ve aynı sonuçları veriyor, ancak her büyüklükteki bir uygulamada çarpıcı biçimde farklı davranışlar gösterebiliyor. Programlama 101'den çıktıktan sonra, Programming 102'nin aynı dili kullanacağı garantisi yoktur. Bir dizi kavramından başlarsanız, sadece "diyebilirsiniz"

Giriş kursunda "dizi" yi "dizi" tercih etmenin bir başka nedeni de, dizilerin anlaşılması çok kolay olmasıdır: bytesUygulamaya bağlı olarak dizinin sonunu veya uzunluğunu belirtmek için 20 dizisi 20 bayt (artı bir çift ekler) ).

Bir "Liste" tamamen farklı bir su ısıtıcısıdır ve temelde farklı performans özelliklerine sahip birçok farklı şekilde (ArrayList, LinkedList ve muhtemelen unuttuğum bir çift) uygulanabilir. Farklı Liste sınıfları ne yaptığını cesareti anlamadan, kullanmak gerekirken anlamlı bir tartışma olamaz List foo = new ArrayList()vs List foo = new LinkedList(). Öğrencinin bir Liste uygulamasını kullanmasını sağlamaya çalışırsanız, birisi diğer uygulamalardan biri yerine neden ArrayList'i kullandığınızı soracaktır. Ve "ArrayList", "Array" kelimesini içerir ve biri tarafından desteklenir, bu yüzden "dizi" den "ArrayList" e kadar büyük bir mantık atlaması değildir.

Popüler inanışın aksine, özellikle statik boyutların bir listesiyle uğraşırken, Listelerde dizileri kullanmanın bir anlamı vardır. İşte bir çift:

  • Arama ve yineleme biraz daha hızlıdır, çünkü genel bir yöntem çağrısı foo[n]başlamasıyla uğraşmazsınız : dereferences ve bazı sahne arkası işaretçisi aritmetik işlemlerini foo.get(n)yapar, zorunluluk çıkarması, yöntem çağrısı yapması, ikinci bir değişkenliği çıkarması ve daha sonra da işaretçi aritmetik işlemi yapması gerekir. (eğer bir ArrayList kullanıyorsanız; LinkedLists listenin her elemanı üzerinde potansiyel olarak yinelenmelidir).
  • Başlatma çok daha temiz: int[] foo = new int[]{1, 2, 3, 4, 5}vs. Another StackOverflow sorusundaki öneriler

Dizileri toplu olarak yendiklerinde diğer bir senaryo, elementlerin kullanılabilir hale geldiği dizinin, nihai konumlarının bilineceği dizilim ile eşleşmesi, ancak dizinin eşleşmemesidir. Eğer bu bir permütasyona sahipse perm, int[256]kolayca bir dizi ile ters çevrilebilir: int[] inv = new int[256]; for (int i=0; i<256; i++) inv[perm[i]]=i; birinin yazabileceği bir şeyin bir ArrayList<>o kadar temiz olacağını sanmıyorum .
Supercat

@supercat Bu, dinamik dizilerle ilgili bir sorun değil, sadece özel bir uygulama; ArrayListkolayca belirli bir boyutta varsayılan olarak başlatılmış bir liste oluşturan bir yapıcı verilebilirdi.
Doval

Bir dizi listesinin, metot çağırma ek yükü ile ilgilenmesi iddiasını destekleyecek kaynaklarınız var mı? Teoride öyle, ama pratikte sıraya getgirip setgirmediğimde şaşırırdım.
Doval

@Doval: İyi tasarlanmış bir dilin / çerçevenin, dizilerin dışına kolayca öğe ekleyebilecek dinamik bir dizi türü sağlamaması için bir neden yoktur, ancak Java böyle bir tür sağlamamaktadır.
supercat

@Doval: İçinde olsa getve sıralanabilse bile set, gibi bir şey myList.set(23,myList.get(23)+1)hiçbir zaman olduğu kadar verimli olamaz myArray[23]+=1. Ayrıca, hatta boks gerek olmazdı türleri için, çok sürpriz olurdu tüm titremeleri olabilir şey eşdeğer for (i=0; i<1000; i++) myList2.set(i+2000,myList2.get(i+3000));olan performans yerde yakın bir şey haline System.arrayCopy(myArray1,3000,myArray2,2000,1000); bir çerçevenin dinamik dizi türü hızlı kopyalama menzilli operasyon teklif olmamalıdır neden yok, ama Java değil.
supercat,

7

Java, herhangi bir türdeki değişkenlerin dizilere depolanmasını sağlar. Aksine, ArrayListyalnızca referansların depolanmasına izin verir. Bu nedenle ArrayList, ilk önce otomatik kutlamanın ilkelleri referans türlerine nasıl dönüştürecağını ve otomatik olarak kutunun kaldırılmasının bazen referans türlerini ilkellere nasıl dönüştüreceğini ele almadan yararlı bir şekilde tartışmayabilir :

for (int i=10; i<=10000; i*=10)
{
    ArrayList<Integer> l = new ArrayList<Integer>();
    l.add(i);
    l.add(i);
    l.add(l.get(0));
    System.out.print("i=" + i);
    System.out.print(" #0==i:" + (l.get(0)==i));
    System.out.print(" #1==i:" + (l.get(1)==i));
    System.out.print(" #2==i:" + (l.get(2)==i));
    System.out.print(" #0=#1:" + (l.get(0)==l.get(1)));
    System.out.print(" #1=#2:" + (l.get(1)==l.get(2)));
    System.out.println(" #0=#2:" + (l.get(0)==l.get(2)));
}

Kodun int[3]yerine bir kullanmış ArrayListolsaydı, sürpriz olmazdı. Her üç element de birbiriyle eşit olarak karşılaştırılır i. Kullanarak ArrayListlistenin üç elemanları her zaman eşit karşılaştıracak bile, bununla birlikte, ive birinci ve üçüncü zaman birbirine göre eş olacaktır, ilk iki eleman, her birbirine eşit olan tek olacaktır i, 10 ya da 100 1, ancak (çoğu uygulamada) i1000 veya 10000 olduğunda.


Neden # 0 ve # 1'in 1 veya 10 veya 100 olduklarında eşit olacağını açıklayabilir misiniz? O noktaya kadar takip ettim.
Matthew

2
@MatthewRead: IntegerSınıf, tipik olarak -128..127'yi genişleten bir dizi değer için IntegerCacheönceden başlatılmış Integernesneleri tutan iç içe geçmiş bir sınıfa sahiptir ; bu aralığın dışındaki bir değere boks yapmak yeni bir nesne oluşturmayı gerektirir, ancak önbelleğe alınmış aralıktaki bir değeri kutuya koymak, içinde depolanan önceden başlatılmış nesnelerden birine referansta bulunacaktır IntegerCache.cache. Herhangi bir iyi Java programcısının Integer, aynı değeri içeren iki tür değişkenlerin eşit karşılaştırılabileceğini veya karşılaştırmayabileceğini veya bunun çok erken ortaya konmasının öğrencilerin terörden kaçmalarını sağlayabileceğini bilmesi gerekir .
supercat

Huh, hiçbir zaman önceden-cisimleştirilmiş cisimler yüzünden olduğunu tahmin edemezdim. Bilgi için teşekkürler!
Matthew

1
@MatthewRead: Java'nın belirli türde gizli dönüşümlere izin vermemesini diliyorum ==. Otomatik unboxing atma olasılığı göz önüne alındığında, tamamen izin vermeme eğiliminde olurdum, ancak onun davranışları ==özellikle korkunç. ==Operatör ayrıca gibi durumlarda kötü davranır 16777217==16777216f[gerçek raporları] ve için örtülü dönüşüm long v=Math.Round(123456789), w=Math.Round(123456789012345)beklenmedik çıkmaya açıktır [o ifadeler verecektir tahmin edebiliyor musunuz?]
SuperCat

Gelince IntegerCache, performansa yardımcı olabileceği kesin zamanlar vardır, ancak sık sık çalışacak türden Sadece Düz Yanlış olan koda neden olabilir. Bazı açılardan, boksörün iki tamsayılı önbellekten nesnelerin yarı rasgele rasgele döndürüleceği ve önbellek öğelerinin yenileriyle yarı rasgele rasgele değiştirileceği bir mod olmasını diliyorum, böylece değerlerin boks davranışına dayanan kod -12. çok uzun zamandır başarılı olamayacaksınız.
supercat

6

ArrayListDahili olarak bir dizi kullanması nedeniyle ilk önce dizilerin nasıl kullanılacağını öğretmenin anlamlı olacağını düşünüyorum . ArrayListSınıf olarak adlandırılan bir üye değişkeni olan elementDatabir olan Objectbir dizi.

JDK ArrayList kaynak kodundan :

/**
 * The array buffer into which the elements of the ArrayList are stored.
 * The capacity of the ArrayList is the length of this array buffer.
 */
private transient Object[] elementData;

Öğeleri eklediğinizde, güncellediğinizde, aldığınızda veya kaldırdığınızda, ArrayListbu işlemleri yapmak için bu dahili diziyi kullanır. Kullanıcı Ixrec'in çoktan belirttiği gibi - ArrayListgenellikle üzerinde çalışılması daha kolay olan sadece üst seviye bir soyutlamadır.


Ancak bir dizi dahili olarak bir bellek bloğuna bir işaretçi kullanır. Neden bu özel soyutlama seviyesinde başlasın?

Soru şu şekilde etiketlendi: JavaNormalde ne zaman kullanabileceğinize neden dizileri öğretiyordu ArrayList? Java'da işaretçiler yoktur. Doğru ya da yanlış, C / C ++ 'nın öğrencileri Java ile başlatmak için daha iyi bir dil olduğu görüşündeyim. Programlamadaki birçok konu, C / C ++ bilgisine sahip olarak daha iyi anlaşılabilir.
Derek W

3

Bu listenin, söylediğiniz gibi çalışmakla gerçekten daha kolay olduğunu varsayarsak, bu gerçekten önemli değil. Öğrenme, "temelden karmaşık" a, "kolaydan zor" a göre daha fazladır. Temeller önemli olmasaydı, o zaman bilgisayar bilimi akademik bir alan olmazdı. Çevrimiçi öğreticilerden varolan çerçeveleri / kitaplıkları kullanarak uygulamaları nasıl tıklatacağınızı öğrenebilirsiniz. (Tabii ki, birisi bu kütüphaneleri yazmak zorunda ... ve biri ArrayListde ilk olarak uygulamak zorunda ...)


Bir çok durumda, ArrayListayrı bir dizi ve "liveItems" sayımı kullanılarak kullanım daha iyi ele alınabilir, ancak dizi ile çalışmanın ve bir araya getirmenin dışında birlikte saymanın uygun bir yolu yoktur.
supercat

2

Çünkü akademik eğitimdeki en önemli şey, yaptığınız şeyleri tanımlamak için doğru terminolojiyi kullanmayı öğretmektir.

Liste bu diziden başka bir şeydir. Ve java.util.Listbir arayüz olduğu için Java'da kullanamazsınız . Genellikle java.util.ArrayListbir Liste uygulaması olan bir liste değil, dinamik dizi etrafında bir nesne sarmalayıcı olanı kullanırsınız . Yani bir 'Liste' kullandığınızı söylüyorsunuz ama bir dizi kullanıyorsunuz.

Bu terminolojik kaosu atlamak ve dizilerin ne olduğunu öğrencilere öğrenmek için dizileri kullanmak oldukça mantıklı. Java'da diziler kullanıyorsanız, en azından dizileri kullanırsınız.

Açıkçası, Java ile programlama öğretmenin neden iyi bir fikir olmadığı da bir tartışma. Programlamanın temel kavramlarını doğru bir şekilde öğrenmek zor.


ya hashmap? bir dizi sadece bir çeşit hashmap'tir ..
Thufir

@Thufir bir dizi nasıl bir hashmap olabilir? Bunlar tamamen farklı veri yapılarıdır.
Danubian Sailor

hashmap ile bir diziyi temsil edebilirsiniz. hangisi daha "temel"? Hashmap'in kavramsal olarak daha ilginç olduğunu savunuyorum.
Thufir

1
@Tufir hayır, yapamazsınız. Sadece taklit edebilirsiniz. Dahili olarak her veri yapısı olduğu gibi olacaktır. Bunlar temelde ve kavramsal olarak farklı şeyler. Bu nedenle, Java veya JavaScript gibi son derece soyut dillerle programlama öğrenmeye başlamak kötü bir fikirdir. Veri yapısının gerçekte ne olduğu tam olarak belli değil.
Danubian Sailor

1

Kelimenin tam anlamıyla hiç dizi görmediniz veya hiç kullanmadınız mı? Listelere ek olarak onları her zaman kullanıyoruz . Genellikle Java kullanmıyoruz, ancak belirgin benzerlik gösteren birçok dil kullanıyoruz.

Diziler ve Listeler arasında, biri daha hafif ve ek olarak, noktaya daha çok, diğerinin ise daha fazla işlevselliği var. Programlamada genel bir kural olarak, temelde bu çizgiler boyunca bölünmüş iki benzer tip olduğunda, gerçekten meraklısı birine ihtiyacınız olmadıkça daha hafif olana gitmelisiniz. Genel giderlerin azaltılmasına ek olarak, bu aslında programdaki karışıklık ve durum miktarını ve özellikle de kodunu idare etmeye yardımcı olur . Test sırasında bir şeyler ters giderse, bakacak daha az yeriniz vardır; ve daha önemlisi, diziler ve Listeler durumunda, insanlar gerçekte kullandığınız ve onunla yapmaya çalıştığınız şeyin sınırlı kapsamı hakkında daha iyi bir fikir edinir.

Ve evet, akademik bir bakış açısıyla, öğrencilere temelleri öğretmenin ek nedeni vardır. Ancak bu biraz daha derine gider. Diziler ve Listeler, genellikle daha hafif ağırlıkta olan örneklerin altında yatan ve genellikle saran sarılı, daha hacimli tiplere iyi bir örnektir. Listelerde altta yatan diziler olmasa bile, onlar olduğu gibi dışa doğru davranırlar. Birine bir Listenin ne olduğunu öğretmenin bir kısmı, onlara bir dizinin ne olduğunu öğretmektir.

Bunun belki de C ++ gibi bir dilde elden çıkmadığını görebiliyordum. Diziler temelde olduğundan daha fazla sıyrılmıyorlardı, ancak daha yüksek seviyeli dillerde neredeyse kendileri için listeler. Belirli bir durumda ihtiyaçlarınızı mükemmel bir şekilde yerine getiriyorlarsa, neden başka bir şey kullanmanız gerekiyor?


Bir listenin "daha fazla" işlevselliğe sahip olduğunu söyleyemem, "farklı" işlevselliğe sahip olduğu kadar. T[]Herhangi bir siparişte öğeleri kabul etmek için kapıdan çıkar çıkmaz yeni bir öğe hazırlanırken, bir ArrayList<T>öğenin değiştirilmeden önce sırayla eklenmesini gerektirir. A T[], benzer boyuttaki bir aralığa rastgele bir öğe aralığını T[]nispeten hızlı bir şekilde kopyalayabilir , öte yandan ArrayList<T>bir listeden öğeleri tek tek okumayı ve diğerine kaydetmeyi gerektirir - çok daha yavaş ve daha az kullanışlı.
supercat,
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.