Bu ekleme siparişinin bir haritadaki önemi nasıl iletilir?


24

Veritabanından bir takım tılsım getirip haritaya yerleştiriyorum. Veritabanı sorgusu maliyetlidir.

Haritadaki öğelerin açıkça doğal sıralaması yoktur , ancak ekleme sırası yine de önemlidir. Haritayı sıralamak ağır bir işlem olacaktır, bu nedenle sorgu sonucunun istediğim şekilde sıralandığını göz önüne alarak bunu yapmaktan kaçınmak istiyorum. Bu nedenle, yalnızca sorgu sonucunu LinkedHashMapa'ya kaydederim ve haritayı DAO yönteminden döndürürüm:

public LinkedHashMap<Key, Value> fetchData()

processDataHarita üzerinde bazı işlemler yapması gereken bir yöntemim var - bazı değerleri değiştirmek, bazı yeni anahtarlar / değerler eklemek. Olarak tanımlanır

public void processData(LinkedHashMap<Key, Value> data) {...}

Bununla birlikte, birkaç linter (Sonar vb.) , 'Veri' tipinin “LinkedHashMap” uygulaması yerine “Harita” gibi bir arayüz olması gerektiğinden şikayetçidir ( mürekkep balığı S1319 ).
Yani temelde yapmam gerektiğini söylüyor

public void processData(Map<Key, Value> data) {...}

Ancak, yöntem imzasının harita sırasının önemli olduğunu - içindeki algoritmaya önem verdiğini processData- böylece yöntemin rastgele herhangi bir haritaya geçmediğini söylemesini istiyorum .

Kullanmak istemiyorum SortedMap, çünkü ( javadoc'tanjava.util.SortedMap ) " tuşlarının doğal sırasına göre sıralanır veya tipik olarak sıralanmış harita oluşturma zamanında sağlanan bir Karşılaştırıcı tarafından sipariş edilir ."

Anahtarlarımın doğal bir düzeni yok ve hiçbir şey yapmamak için bir Karşılaştırıcı oluşturmak çok ayrıntılı görünüyor.

Ve hala bir harita olmasını, putyinelenen anahtarlardan vb. Sakınmak için yararlanmak istiyorum. Olmazsa, bir dataolabilirdi List<Map.Entry<Key, Value>>.

Öyleyse, yöntemimin zaten sıralanmış bir harita istediğini nasıl söyleyebilirim ? Ne yazık ki, java.util.LinkedMaparayüz yok , yoksa onu kullanırdım.

Yanıtlar:


56

Öyleyse kullan LinkedHashMap.

Evet , kullanmak gerekir Mapmümkünse belli bir uygulama üzerinde ve evet , bu ise en iyi yöntem.

Bununla birlikte, bu Mapaslında uygulamanın önemli olduğu tuhaf bir durumdur . Bu, kullandığınızda kodunuzdaki vakaların% 99,9'u için geçerli olmayacak Mapve yine de buradasınız, bu% 0,1 durumda. Sonar bunu bilemez ve bu yüzden Sonar size belirli bir uygulamayı kullanmaktan kaçınmanızı söyler çünkü çoğu durumda doğru olacaktır.

Belli bir uygulamayı kullanmak için dava açabilirseniz, bir domuzun üzerine ruj koymayı denemeyin. İhtiyacın var LinkedHashMap, değil Map.

Bu, eğer programlamada yeni iseniz ve bu cevaba karıştıysanız, bunun en iyi uygulamaya karşı çıkmanıza izin verdiğini sanmayın, çünkü yapmaz. Ancak bir uygulamanın bir başkasıyla değiştirilmesi kabul edilemezse, yapabileceğiniz tek şey o özel uygulamayı kullanmak ve Sonar'a lanetlenmektir.


1
Sevdiğim Pragmatik yaklaşım.
Vidar S. Ramdal

20
Neredeyse tamamen cevaba katılıyorum. Sadece Sonar'a lanetli olmadığını söylerdim. Belirli bir hatayı / uyarısını yoksaymak için her zaman yapılandırabilirsiniz. Bkz stackoverflow.com/questions/10971968/...
Vladimir Stokic

11
if you are new to programming and stumble upon this answer, don't think this allows you to go against best practice because it doesn't.- İyi tavsiye, "en iyi uygulama" diye bir şey olsaydı. Daha iyi tavsiye: doğru kararların nasıl alınacağını öğrenin. Mantıklıysa uygulamayı takip edin, ancak araçların ve otoritelerin düşünme sürecinizi yönlendirmesini sağlayın, dikte etmeyin.
Robert Harvey

13
Not: Sonar size bir şey bildirdiğinde, onu "çözülmeyecek" olarak kapatabilir ve neden yapmayacağınız gibi bir not bırakabilirsiniz. Sadece sonar sizi rahatsız etmeyi bırakmayacak, aynı zamanda bunu neden yaptığınıza dair bir iziniz olacak.
Walfrat

2
Bunu genel bir istisna haline getiren hususun LinkedHashMap'in bu uygulamaya özel olan ve herhangi bir arayüzde ifade edilmeyen bir sözleşmesi olduğunu düşünüyorum. Bu olağan bir durum değil. Dolayısıyla, bu sözleşmeye bağlılığı ifade etmenin tek yolu uygulama türünü kullanmaktır.
Dana

21

Üç şeyle savaşıyorsun:

Birincisi, Java'nın konteyner kütüphanesidir. Taksonomisinde hiçbir şey size sınıfın öngörülebilir bir düzende yinelenip tekrarlanmadığını belirlemenin bir yolunu vermez. Tip kontrolünü (ve aynı şekilde davranan alternatif uygulamaların kullanımını) mümkün kılan, IteratesInInsertedOrderMapuygulanabilecek bir arayüz yoktur LinkedHashMap. Bu muhtemelen tasarım gereğidir, çünkü onun ruhu, gerçekten soyut gibi davranan nesnelerle başa çıkmanız gerektiğidir Map.

İkincisi, linter'inizin söylediklerine müjde gibi davranılması gerektiğine ve söylediği hiçbir şeyi görmezden gelmenin kötü olduğu inancıdır. Bugünlerde iyi uygulama için geçenlerin aksine, linter uyarıları kodunuzu iyi çağırmanın önündeki engeller değildir. Yazdığınız kod hakkında akıl yürütmeniz istenir ve uyarının haklı olup olmadığını belirlemek için deneyiminizi ve kararınızı kullanın. Sebepsiz uyarılar, hemen hemen her statik analiz aracının, kodu incelediğinizi, yaptığınız şeyin tamam olduğunu ve gelecekte şikayet etmemelerini gerektiğini söyleyen bir mekanizma sağlamasının sebebidir.

Üçüncüsü, ve bu muhtemelen onun eti LinkedHashMap, iş için yanlış bir araç olabilir. Haritalar sıralı değil, rastgele erişim için tasarlanmıştır. Eğer processData()sadece sırayla kayıtların yineler ve anahtar ile diğer kayıtları bulmak gerekmez, sen belirli bir uygulama zorluyorlar Mapbir işi yapmak için List. Öte yandan, her ikisine de gereksinim duyuyorsanız LinkedHashMap, doğru araç çünkü istediğiniz şeyi yaptığınız biliniyor ve gereksinim duymakta haklısınız.


2
"LinkedHashMap iş için yanlış bir araç olabilir". Evet belki. İhtiyacım olduğunu söylediğimde OrderedMapsöyleyebilirim UniqueList. Tanımlı bir yineleme sırasına sahip bir tür koleksiyon olduğu sürece, bu, ekleme sırasında yinelenenlerin üzerine yazar.
Vidar S. Ramdal

2
@ VidarS.Ramdal Veri tabanı sorgusu, kopyaları ayıklamak için ideal bir yer olacaktır. Veritabanınız bunu yapamazsa Set, listeyi bir noktaya getirmenin bir yolu olarak , sadece anahtarları geçici olarak tutabilirsiniz .
Blrfl

Oh, anladığım kadarıyla karışıklığa neden oldum. Evet, veritabanı sorgusu sonucu yinelenen içermiyor. Ancak processDataharitayı değiştirir, bazı değerleri değiştirir, bazı yeni anahtarlar / değerler sunar. Öyleyse processData, a dışında bir şey üzerinde çalışıyorsa, kopyaları tanıtabilir Map.
Vidar S. Ramdal

7
@ VidarS.Ramdal: Kendinizinkini UniqueList(veya OrderedUniqueList) yazmanız ve kullanmanız gerekiyor gibi geliyor . Oldukça kolay ve kullanım amacınızı daha net hale getiriyor.
TMN

2
@TMN Evet, bu yönde düşünmeye başladım. Önerinizi bir cevap olarak göndermek istiyorsanız, kesinlikle benim oyum olacak.
Vidar S. Ramdal

15

Elinizden gelen tek LinkedHashMapşey, kopyaların üzerine yazma yeteneği ise, ancak gerçekten a olarak kullanıyorsanız List, bu kullanımı kendi özel Listuygulamanızla iletmeniz daha iyi olur . Onu mevcut bir Java koleksiyonları sınıfına dayandırabilir addve removedestek deponuzu güncellemek ve benzersizliği sağlamak için anahtarı takip etmek için yöntem ve yöntemleri geçersiz kılabilirsiniz . Buna benzer bir ad ProcessingListvermek, processDatayönteminize sunulan argümanların belirli bir şekilde ele alınması gerektiğini açıkça ortaya koyacaktır .


5
Bu yine de iyi bir fikir olabilir. Heck, ProcessingListbir takma ad olarak oluşturduğu tek satırlık bir dosyaya bile sahip olabilirsiniz LinkedHashMap- genel arayüzü sağlam tuttuğunuz sürece daha sonra başka bir şeyle değiştirmeye karar verebilirsiniz.
CompuChip

11

"Sistemimin bir bölümünü LinkedHashMap üreten bir sistemim var ve sistemimin başka bir bölümünde, yalnızca başka bir işlem tarafından üretilenlerin kazandığı ilk bölüm tarafından üretilen LinkedHashMap nesnelerini kabul etmem gerekiyor" dediğinizi duyuyorum. t düzgün çalışmayın. "

Bu, buradaki sorunun aslında aradığınız verilere uyduğu için LinkedHashMap'i kullanmaya çalıştığınızı düşündürüyor, ancak aslında sizin oluşturduğunuzdan başka bir örnekle değiştirilemiyor. Aslında yapmak istediğin şey, ilk bölümünün yarattığı ve ikinci bölümünün tükettiği kendi arayüzünü / sınıfını oluşturmak. "Real" LinkedHashMap'i sarabilir ve bir Harita alıcı sağlayabilir veya Harita arayüzünü uygulayabilir.

Bu, CandiedOrange'in cevabından biraz farklı, bu yüzden uzatmak yerine gerçek Harita'yı (ve gerekirse çağrıları delege etmeyi) içine almayı tavsiye ediyorum. Bazen bu stillerin kutsal savaşlarından biri, ama bana "ek eşyalar içeren bir harita" değil, "dahili olarak bir harita ile temsil edebileceğim faydalı durum bilgisi çantasım" değil.

Bu şekilde dolaşmanız gereken iki değişkeniniz olsaydı, muhtemelen fazla düşünmeden bunun için bir sınıf yapmış olursunuz. Ancak bazen sadece bir üye değişkeni olsa bile bir sınıfa sahip olmak yararlıdır, çünkü sadece mantıksal olarak aynı şeydir, "değer" değil, "işlemimin sonucu daha sonra yapılması gerekenler" olur.


Bu düşüncenin gibi - Ben orada olmuştur :) MyBagOfUsefulInformationbunu doldurmak için bir yöntem (veya yapıcı) gerekir: MyBagOfUsefulInformation.populate(SomeType data). Ancak datasıralanmış sorgu sonucu olması gerekir. Yani ne olur SomeTypeolmasa olmak LinkedHashMap? Bu Catch 22'yi kırabileceğimden emin değilim.
Vidar S. Ramdal

Neden MyBagOfUsefulInformationDAO tarafından yaratılamıyor veya sisteminizde veri üreten herhangi biri? Neden alttaki haritayı, Kodun geri kalan kısmına Çanta üreticisinin ve tüketicisinin dışında bırakmanız gerekiyor?

Mimarinize bağlı olarak, nesnenin yalnızca istediğiniz üretici tarafından oluşturulabileceğini zorunlu kılmak için özel / korumalı / yalnızca paketi oluşturan bir kurucu kullanabilirsiniz. Ya da sadece doğru bir "fabrika" tarafından yaratılabilmesi için bir kongre olarak yapmanız gerekebilir.

Evet, MyBagOfUsefulInformationDAO yöntemine bir parametre olarak geçerek biraz benzer bir şey yaparak
bitirdim

4

LinkedHashMap, aradığınız ekleme siparişi özelliğine sahip tek java haritasıdır. Bu yüzden Bağımlılık İnversiyon Prensibi'ni atmak cazip ve hatta pratiktir. İlk önce, onu takip etmek için ne gerektiğini düşünün. İşte SOLID sizden ne yapmanızı ister?

Not: adı Ramdal, bu arabirimin tüketicisinin bu arabirimin sahibi olduğunu bildiren açıklayıcı bir adla değiştirin . Hangi ekleme emri önemli olup olmadığına karar veren otorite yapar. Eğer bunu sadece ararsanız, InsertionOrderMapgerçekten noktayı kaçırdınız.

public interface Ramdal {
    //ISP asks for just the methods that processData() actually uses.
    ...
}

public class RamdalLinkedHashMap extends LinkedHashMap implements Ramdal{} 

Ramdal<Key, Value> ramdal = new RamdalLinkedHashMap<>();

ramdal.put(key1, value1);
ramdal.put(key2, value2);

processData(ramdal);

Ön tarafta büyük bir tasarım mı var? Belki, bunun dışında bir uygulamaya ihtiyaç duymanızın ne kadar muhtemel olduğunu düşündüğünüze de bağlıdır LinkedHashMap. Ancak DIP'yi sadece büyük bir ağrı olacağı için takip etmiyorsanız, kazan plakasının bundan daha acı verici olduğunu düşünmüyorum. Bu, dokunulmaz kodun yapmadığı bir arabirim oluşturmasını istediğimde kullandığım kalıp. En acı verici kısım gerçekten iyi isimleri düşünmektir.


2
İsmi severim!
Vidar S. Ramdal

1

Düşünce için iyi öneri ve yiyecek bir sürü için teşekkürler.

Yeni bir harita sınıfı oluşturarak processData, örnek bir yöntem yaparak genişlettim :

class DataMap extends LinkedHashMap<Key, Value> {

   processData();

}

Sonra DAO yöntemini yeniden haritalandırdım, böylece bir harita döndürmüyor, bunun yerine bir targetharitayı parametre olarak alıyor :

public void fetchData(Map<Key, Value> target) {
  ...
  // for each result row
  target.put(key, value);
}

Böylece, a'yı DataMapdoldurmak ve verileri işlemek, şimdi algoritmanın bir parçası olan başka yerlerden gelen bazı başka değişkenler olduğundan iyi olan iki aşamalı bir işlemdir.

public DataMap fetchDataMap() {
  var dataMap = new DataMap();
  dao.fetchData(dataMap);
  return dataMap;
}

Bu, Harita uygulamamın girdilerin nasıl eklendiğini kontrol etmesine izin verir ve sipariş gereksinimini gizler - artık bir uygulama detayıdır DataMap.


0

Kullandığınız veri yapısının bir nedeni olduğunu bildirmek istiyorsanız, yöntemin imzasının üstüne bir yorum ekleyin. Gelecekte başka bir geliştirici bu kod satırına rastlar ve bir araç uyarısı görürse, yorumu da farkedebilir ve sorunu "düzeltmekten" kaçınabilir. Yorum yoksa, hiçbir şey imzayı değiştirmelerini engelleyemez.

Uyarıları bastırmak benim görüşüme göre yorum yapmaktan daha düşüktür, çünkü bastırmanın kendisi uyarının neden bastırıldığını açıklamamaktadır. Uyarı bastırma ve yorum bir arada da iyi olacak.


0

Öyleyse, içeriğinizi burada anlamaya çalışayım:

... yerleştirme sırası önemli ... Haritayı sıralamak ağır bir işlem olurdu ...

... sorgu sonucu zaten istediğim şekilde sıralandı

Şimdi, şu anda ne yapıyorsanız:

Veritabanından bir takım tılsım getiriyorum ve bir haritaya koyuyorum ...

Ve işte şu anki kodunuz:

public void processData(LinkedHashMap<Key, Value> data) {...}

Benim önerim aşağıdakileri yapmaktır:

  • Bağımlılık enjeksiyonunu kullanın ve bir miktar MyTupleRepository'yi işleme yöntemine enjekte edin (MyTupleRepository, tuple nesnelerinizi genellikle DB'den alan nesneler tarafından uygulanan bir arabirimdir);
  • İşleme yöntemine dahili olarak, belirli LinkedHashMap koleksiyonuna depodan (yani sipariş edilen verileri döndüren DB) verileri koyun, çünkü bu işlem algoritmanın iç detayıdır (çünkü verilerin veri yapısında nasıl düzenlendiğine bağlıdır) );
  • Unutmayın ki, bu zaten ne yaptığınızla ilgili bir şey değil, ancak bu durumda bu işleme yönteminde yapılacaktır. Deponuz başka bir yerde başlatılıyor (zaten verileri döndüren bir sınıfınız var, bu örnekte bu depodur)

Kod örneği

public interface MyTupleRepository {
    Collection<MyTuple> GetAll();
}

//Concrete implementation of data access object, that retrieves 
//your tuples from DB; this data is already ordered by the query
public class DbMyTupleRepository implements MyTupleRepository { }

//Injects some abstraction of repository into the processing method,
//but make it clear that some exception might be thrown if data is not
//arranged in some specific way you need
public void processData(MyTupleRepository tupleRepo) throws DataNotOrderedException {

    LinkedHashMap<Key, Value> data = new LinkedHashMap<Key, Value>();

    //Represents the query to DB, that already returns ordered data
    Collection<MyTuple> myTuples = tupleRepo.GetAll();

    //Optional: this would throw some exception if data is not ordered 
    Validate(myTuples);

    for (MyTupleData t : myTuples) {
        data.put(t.key, t.value);
    }

    //Perform the processing using LinkedHashMap...
    ...
}

Sanırım bu Sonar uyarısından kurtulacak ve aynı zamanda işleme yönteminin gerektirdiği özel imza düzeninde belirtilecek.


Hmm, ama depo nasıl somutlaştırılabilir? Bu sadece problemi başka bir yere taşımak olmaz mıydı ( MyTupleRepositoryyaratıldığı yere ?)
Vidar S. Ramdal

Sanırım Peter Cooper'ın cevabında olduğu gibi aynı sorunu yaşayacağım .
Vidar S. Ramdal

Önerim, Bağımlılık Enjeksiyon Prensibi'nin uygulanmasını içerir; bu örnekte; MyTupleRepository, bahsettiğiniz dosya türlerini alma özelliğini tanımlayan (DB'yi sorgulayan) bir arabirimdir. Burada, bu nesneyi işleme yöntemine enjekte ettiniz. Zaten verileri döndüren bir sınıfınız var; bu yalnızca onu bir arabirimde özetler ve nesneyi aslında işlemin bir parçası olduğu için LinkedHashMap'i dahili olarak kullanan 'processData' yöntemine enjekte edersiniz .
Emerson Cardoso

Ne önerdiğim konusunda daha net olmaya çalışarak cevabımı değiştirdim.
Emerson Cardoso

-1

Bu soru aslında veri modelinizle bir araya getirilen bir çok sorun. Bunları teker teker çözmeye başlamanız gerekir. Bulmacanın her bir parçasını basitleştirmeye çalışırken daha doğal, sezgisel çözümler ortadan kalkar.

Sorun 1: DB Siparişine bağlı olamaz

Verilerinizi sıralama açıklamalarınız net değil

  • En büyük potansiyel sorun, bir ORDER BYfıkra ile veritabanınızda açık bir sıralama belirtmemenizdir . Çok pahalı görünmediğinden değilseniz, programınızın bir hatası var . Belirtilmemişse, veritabanlarının sonuçları herhangi bir sırayla döndürmesine izin verilir ; Sorguya birkaç kez koştuğunuz için rastgele veriyi sırayla döndürmenize bağlı olamazsınız. Sıra değişebilir çünkü sıralar diskte yeniden düzenlenir, ya da bazıları silinir, yenileri yer alır ya da bir dizin eklenir. Sen gerekir bir belirtmek ORDER BYçeşit maddesini. Doğruluk olmadan hız değersizdir.
  • Ayrıca, ekleme siparişi ile ne demek istediğinizi de belli etmiyor. Veritabanına kendisi söz ediyorsanız, gereken aslında bu izleyen bir sütun var ve bu olmalı senin dahil edilmesi ORDER BYfıkra. Aksi takdirde, böcek var. Eğer böyle bir sütun henüz mevcut değilse, bir tane eklemeniz gerekir. Bunun gibi sütunlar için tipik seçenekler, ekleme zaman damgası sütunu veya otomatik artan anahtardır. Otomatik artan anahtar daha güvenilirdir.

Problem 2: Hafıza sıralamada verimli olma

Verileri beklediğiniz sıraya göre döndürmenin garanti edildiğinden emin olduktan sonra , bellek türlerini çok daha verimli hale getirmek için bu gerçeği kaldırabilirsiniz . Sorgunuzun sonuç kümesine bir row_number()veyadense_rank() sütun (veya veritabanınızın eşdeğeri) eklemeniz yeterlidir. Artık her satırda, siparişin ne olması gerektiği konusunda doğrudan bir gösterge verecek bir endeks var ve bunu hatıra olarak saklayabilirsiniz. Dizine anlamlı bir ad (benzeri sortedBySomethingIndex) verdiğinizden emin olun .

Viyola. Şimdi artık veritabanı sonuç kümesi sırasına bağlı kalmak zorunda değilsiniz.

Sorun 3: Bu işlemi kodda yapmanız gerekiyor mu?

SQL aslında gerçekten güçlü. Verileriniz üzerinde çok fazla dönüşüm ve toplama yapmanıza izin veren şaşırtıcı bir bildirim dilidir. Çoğu DB bugünlerde çapraz sıra işlemlerini bile destekliyor. Bunlara pencere veya analitik fonksiyonlar denir:

Verilerinizi bu şekilde belleğe mi çekmeniz gerekiyor ? Veya SQL işlevindeki tüm çalışmaları pencere işlevlerini kullanarak yapabilir misiniz? DB'deki çalışmaların tümünü (veya belki de yalnızca önemli bir bölümünü) yapabiliyorsanız, harika! Kod probleminiz ortadan kalkar (veya çok daha basitleşir)!

Problem 4: Buna ne yapıyorsunuz data?

Bunların hepsini DB'de yapamayacağınızı varsayarak, bunu doğru anlamama izin verin. Sen (siz şeylerle kamalıdır Verileri harita alıyorsun yok bunun üzerinde göre sıralamak istiyorum), o zaman konum ilerlerken ekleme talimatına ve bazı anahtarlarının değeri değiştirerek ve ekleyerek yerinde haritayı değiştirerek Yeni olanlar?

Özür dilerim, ama ne halt?

Arayanlar tüm bunlar için endişelenmek zorunda olmamalıdır . Yarattığınız sistem çok kırılgan. Küçük bir yanlış değişiklik yapmak için tek bir aptal hata (belki de kendi başınıza yaptığınız gibi) alır ve her şey kart destesi gibi çöküyor.

İşte belki daha iyi bir fikir:

  • İşlevinizin kabul etmesini sağlayın List.
  • Sipariş problemini çözmenin birkaç yolu var.
    1. Hızlı Arızayı Uygula. Listede işlevin gerektirdiği sırada değilse bir hata atın. (Not: Problem olup olmadığını anlamak için Problem 2'deki sıralama indeksini kullanabilirsiniz.)
    2. Sıralı bir kopya kendiniz oluşturun (sorun yine 2'deki dizini kullanarak).
    3. Haritanın kendisini sırayla oluşturmanın bir yolunu bulun.
  • İhtiyacınız olan haritayı dahili olarak oluşturun, böylece arayan kişi onunla ilgilenmek zorunda kalmaz.
  • Şimdi sahip olduğunuz sıraya göre düzenleyin ve yapmanız gerekeni yapın.
  • Haritayı döndürün veya uygun bir dönüş değerine dönüştürün

Sıralı bir gösterim oluşturmak ve ardından indekslemek için bir anahtar haritası oluşturmak olabilir . Bu, yanlışlıkla kopyaları oluşturmadan sıralanan kopyanızı yerinde değiştirmenize olanak sağlar.

Ya da belki bu daha mantıklı: dataParametreden kurtulun ve processDataaslında kendi verilerini alın. Daha sonra bunu yaptığınızı belgeleyebilirsiniz, çünkü verilerin getirilme şekli konusunda çok özel gereksinimleri vardır . Başka bir deyişle, işlev yapmak kendi tüm süreci, bunun sadece bir parçası; Bağımlılıklar, mantığı daha küçük parçalara bölmek için fazla güçlüdür. (İşlemdeki işlevin adını değiştirin.)

Belki bunlar senin durumun için işe yaramaz. Sorunun tam detayları olmadan bilmiyorum. Ama duyduğumda kırılgan ve kafa karıştırıcı bir tasarım biliyorum.

özet

Bence buradaki problem nihayetinde şeytanın ayrıntıda olduğu. Böyle bir sıkıntı yaşamaya başladığımda, bunun sebebi genellikle çözmeye çalıştığım problem için verilerimi uygunsuz bir şekilde temsil etmemdir. En iyi çözüm, daha iyi bir temsil bulmak ve benim sorunum çözmek için basit (belki kolay değil, basit) olur.

Bu noktayı alan birini bulun: işiniz, sorununuzu basit ve anlaşılır olanlara indirgemek. O zaman sağlam, sezgisel bir kod oluşturabilirsiniz. Onlarla konuş. İyi kod ve iyi tasarım, sizi salak ve anlaşılır oldukları için herhangi bir aptalın düşünebileceğini düşündürür. Belki konuşabileceğin zihniyeti olan kıdemli bir geliştirici vardır.


“Ne anlama gelir ki, doğal sipariş yok ama ekleme siparişi önemli değil mi? Verilerin DB tablosuna hangi siparişin eklendiğini ifade ettiğini söylüyorsunuz, ancak size hangi siparişlerin eklendiğini size söyleyebilecek bir sütununuz yok?” - soru şunu belirtir: "Haritayı sıralamak ağır bir işlemdir, bu nedenle, sorgu sonucunun zaten sıralandığını düşünerek bunu yapmaktan kaçınmak istiyorum" Bu açıkça , verilere hesaplanabilen kesin bir düzen olduğu anlamına gelir , çünkü aksi halde sıralama ağır olmak yerine imkansız olur, ancak tanımlanmış sıra, anahtarların doğal düzeninden farklıdır.
Jules

2
Başka bir deyişle, OP gibi bir sorgunun sonuçları üzerinde çalışıyor select key, value from table where ... order by othercolumnve işlemlerinde sıralamayı sürdürmesi gerekiyor. Kampanya siparişi onlar Bahsettiğiniz olan kendi harita içine ekleme talimatı sorgusunun değil kullanılan emriyle tanımlanan, veritabanına ekleme talimatı . Bu, bunların kullanımı ile açık yapılır LinkedHashMapbir iki özelliklerine sahip bir veri yapısıdır, Mapve a Listanahtar değer çiftleri.
Jules

@Jules Bu bölümü biraz temizleyeceğim, teşekkürler. (Aslında bunu okuduğumu hatırladım, ancak soruyu yazarken bazı şeyleri kontrol ederken, bulamadım. Lol. Yabancı otlara da girdim.) Fakat soru, DB ile ne yaptıkları hakkında net değil. sorgusu ve açık bir sıralama olup olmadıklarını sorgular. Ayrıca "ekleme sırası önemli" diyorlar. Mesele şu ki, sıralama ağır olsa bile, açıkça belirtmemeniz durumunda, işleri doğru bir şekilde doğru şekilde sıralamak için DB'ye güvenemezsiniz. Eğer olursa edilir DB yapıyor, o zaman kodda verimli hale getirmek için bir "endeksi" kullanabilirsiniz.
jpmc26

* cevabı yazma (
Methinks,

Evet, @Jules haklı. Orada olan bir order bysorguda fıkra, ancak (zor olan çözüm olduğunu değil , sadece order by columnJava sıralama reimplementing önlemek istiyorsanız, böylece). SQL rağmen olduğu güçlü (ve biz burada Oracle'ın 11g veritabanı bahsediyoruz), doğası processDataalgoritması çok daha kolay Java ifade etmek yapar. Ve evet, "ekleme sırası" " harita ekleme sırası", yani sorgu sonucu sırası anlamına gelir .
Vidar S. Ramdal
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.