Bagaimana cara mengomunikasikan bahwa urutan penyisipan penting di peta?


24

Saya mengambil satu set tupel dari basis data, dan meletakkannya di peta. Permintaan basis data itu mahal.

Tidak ada urutan alami yang jelas dari elemen-elemen di peta, tetapi urutan penyisipan tetap penting. Menyortir peta akan menjadi operasi yang berat, jadi saya ingin menghindari melakukan itu, mengingat bahwa hasil kueri sudah diurutkan seperti yang saya inginkan. Oleh karena itu, saya hanya menyimpan hasil kueri ke dalam LinkedHashMap, dan mengembalikan peta dari metode DAO:

public LinkedHashMap<Key, Value> fetchData()

Saya memiliki metode processDatayang harus melakukan beberapa pemrosesan pada peta - memodifikasi beberapa nilai, menambahkan beberapa kunci / nilai baru. Ini didefinisikan sebagai

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

Namun, beberapa linter (Sonar dll) mengeluh bahwa Jenis 'data' harus berupa antarmuka seperti 'Peta' daripada implementasi "LinkedHashMap" ( squid S1319 ).
Jadi pada dasarnya itu mengatakan bahwa saya seharusnya

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

Tapi saya ingin tanda tangan metode mengatakan bahwa urutan peta penting - penting untuk algoritma di processData- sehingga metode saya tidak lulus sembarang peta acak.

Saya tidak ingin menggunakan SortedMap, karena itu (dari javadoc ofjava.util.SortedMap ) "dipesan sesuai dengan urutan kuncinya, atau oleh Pembanding yang biasanya disediakan pada waktu pembuatan peta yang diurutkan."

Kunci saya tidak memiliki urutan alami , dan membuat Pembanding untuk tidak melakukan apa pun tampaknya bertele-tele.

Dan saya masih ingin itu menjadi peta, untuk mengambil keuntungan dari putmenghindari duplikat kunci dll. Jika tidak, databisa saja a List<Map.Entry<Key, Value>>.

Jadi bagaimana saya mengatakan bahwa metode saya menginginkan peta yang sudah diurutkan ? Sayangnya, tidak ada java.util.LinkedMapantarmuka, atau saya akan menggunakannya.

Jawaban:


56

Jadi gunakan LinkedHashMap.

Ya , Anda harus menggunakan Maplebih dari implementasi spesifik bila memungkinkan, dan ya , ini adalah praktik terbaik.

Yang mengatakan, ini adalah situasi yang aneh di mana implementasi Mapsebenarnya penting. Ini tidak akan berlaku untuk 99,9% kasus dalam kode Anda saat Anda gunakan Map, namun di sinilah Anda, dalam situasi 0,1% ini. Sonar tidak dapat mengetahui hal ini dan Sonar hanya memberi tahu Anda untuk menghindari penggunaan implementasi spesifik karena itu akan benar dalam banyak kasus.

Saya berpendapat bahwa jika Anda dapat membuat kasus untuk menggunakan implementasi spesifik, jangan mencoba untuk memakai lipstik pada babi. Anda membutuhkan LinkedHashMap, bukan Map.

Ini mengatakan, jika Anda baru dalam pemrograman dan menemukan jawaban ini, jangan berpikir ini memungkinkan Anda untuk menentang praktik terbaik karena tidak. Tetapi ketika mengganti satu implementasi dengan yang lain tidak dapat diterima, satu-satunya hal yang dapat Anda lakukan adalah menggunakan implementasi spesifik itu, dan dikutuk untuk Sonar.


1
Pendekatan pragmatis, yang saya suka.
Vidar S. Ramdal

20
Saya setuju hampir sepenuhnya dengan jawabannya. Saya hanya akan mengatakan bahwa Anda tidak dikutuk untuk Sonar. Anda selalu dapat mengonfigurasinya untuk mengabaikan kesalahan / peringatan tersebut. Lihat 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.- Saran yang bagus, jika ada yang namanya "praktik terbaik." Saran yang lebih baik: pelajari cara membuat keputusan yang tepat. Ikuti latihan jika itu masuk akal, tetapi biarkan alat dan otoritas memandu proses berpikir Anda, bukan mendikte itu.
Robert Harvey

13
Catatan: ketika sonar melaporkan sesuatu kepada Anda, Anda dapat menutupnya sebagai "tidak akan diselesaikan" dan meninggalkan catatan sebagai alasan Anda tidak akan melakukannya. Dengan demikian tidak hanya sonar akan berhenti mengganggumu, tetapi kamu akan memiliki pelacak mengapa kamu melakukan itu.
Walfrat

2
Saya pikir aspek yang membuat ini pengecualian pada prinsip umum adalah bahwa LinkedHashMap memiliki kontrak yang spesifik untuk implementasi itu dan tidak dinyatakan dalam antarmuka apa pun. Ini bukan kasus yang biasa. Jadi satu-satunya cara untuk mengekspresikan ketergantungan pada kontrak itu adalah dengan menggunakan jenis implementasi.
Dana

21

Anda bertengkar tiga hal:

Pertama adalah perpustakaan kontainer Java. Tidak ada dalam taksonomi yang memberi Anda cara untuk menentukan apakah kelas iterate atau tidak dalam urutan yang dapat diprediksi. Tidak ada IteratesInInsertedOrderMapantarmuka yang dapat diimplementasikan oleh LinkedHashMap, yang membuat pengecekan tipe (dan penggunaan implementasi alternatif yang berperilaku dengan cara yang sama) tidak mungkin. Itu mungkin karena desain, karena semangatnya adalah bahwa Anda benar-benar seharusnya mampu menangani objek yang berperilaku seperti abstrak Map.

Kedua adalah keyakinan bahwa apa yang dikatakan oleh orang suci Anda harus diperlakukan sebagai Injil dan bahwa mengabaikan apa pun yang dikatakannya adalah buruk. Bertentangan dengan apa yang berlaku untuk praktik yang baik hari ini, peringatan linter seharusnya tidak menjadi hambatan untuk memanggil kode Anda baik. Mereka diminta untuk beralasan tentang kode yang Anda tulis dan menggunakan pengalaman dan penilaian Anda untuk menentukan apakah peringatan itu dibenarkan atau tidak. Peringatan yang tidak dapat dibenarkan adalah alasan mengapa hampir setiap alat analisis statis menyediakan mekanisme untuk mengatakan bahwa Anda telah memeriksa kode, Anda berpikir apa yang Anda lakukan tidak apa-apa dan bahwa mereka tidak boleh mengeluh tentang hal itu di masa depan.

Ketiga, dan ini mungkin dagingnya, LinkedHashMapmungkin alat yang salah untuk pekerjaan itu. Peta dimaksudkan untuk akses acak, bukan dipesan. Jika processData()hanya mengulangi catatan secara berurutan dan tidak perlu menemukan catatan lainnya dengan kunci, Anda memaksa implementasi khusus Mapuntuk melakukan pekerjaan a List. Di sisi lain, jika Anda membutuhkan keduanya, LinkedHashMapadalah alat yang tepat karena itu dikenal untuk melakukan apa yang Anda inginkan dan Anda lebih dari dibenarkan dalam membutuhkannya.


2
"LinkedHashMap mungkin alat yang salah untuk pekerjaan itu". Ya mungkin. Ketika saya mengatakan saya membutuhkan OrderedMap, saya bisa saja mengatakannya UniqueList. Selama itu adalah semacam koleksi dengan urutan iterasi yang ditentukan, yang menimpa duplikat pada sisipan.
Vidar S. Ramdal

2
@ VidarS.Ramdal Permintaan basis data akan menjadi tempat yang ideal untuk menghilangkan duplikat. Jika basis data Anda tidak dapat melakukannya, Anda selalu dapat menyimpan sementara Setdari kunci-kunci tersebut saat Anda sedang membangun daftar sebagai cara untuk menemukannya.
Blrfl

Oh, saya tahu saya telah menyebabkan kebingungan. Ya, hasil kueri basis data tidak mengandung duplikat. Tetapi processDatamemodifikasi peta, mengganti beberapa nilai, memperkenalkan beberapa kunci / nilai baru. Jadi processDatadapat memperkenalkan duplikat jika beroperasi pada sesuatu selain a Map.
Vidar S. Ramdal

7
@ VidarS.Ramdal: Sepertinya Anda perlu menulis sendiri UniqueList(atau OrderedUniqueList) dan menggunakannya. Ini sangat mudah, dan membuat penggunaan yang Anda maksudkan menjadi lebih jelas.
TMN

2
@ TMN Ya, saya sudah mulai berpikir ke arah itu. Jika Anda ingin memposting saran Anda sebagai jawaban, itu pasti akan mendapatkan upvote saya.
Vidar S. Ramdal

15

Jika semua yang Anda peroleh LinkedHashMapadalah kemampuan untuk menimpa duplikat, tetapi Anda benar-benar menggunakannya sebagai List, maka saya sarankan lebih baik untuk mengkomunikasikan penggunaan itu dengan Listimplementasi kustom Anda sendiri . Anda dapat mendasarkannya pada kelas koleksi Java yang ada dan cukup menimpa apa pun adddan removemetode untuk memperbarui toko dukungan Anda dan melacak kunci untuk memastikan keunikan. Memberi ini nama yang khas seperti ProcessingListakan memperjelas bahwa argumen yang disajikan untuk processDatametode Anda perlu ditangani dengan cara tertentu.


5
Ini mungkin ide yang bagus. Heck, Anda bahkan dapat memiliki file satu baris yang dibuat ProcessingListsebagai alias untuk LinkedHashMap- Anda selalu dapat memutuskan untuk menggantinya dengan yang lain nanti, selama Anda menjaga antarmuka publik tetap utuh.
CompuChip

11

Saya mendengar Anda berkata, "Saya memiliki satu bagian dari sistem saya yang menghasilkan LinkedHashMap, dan di bagian lain dari sistem saya, saya hanya perlu menerima objek LinkedHashMap yang diproduksi oleh bagian pertama, karena yang diproduksi oleh beberapa proses lain akan menang ' t bekerja dengan benar. "

Itu membuat saya berpikir bahwa masalah di sini sebenarnya adalah Anda mencoba menggunakan LinkedHashMap karena sebagian besar cocok dengan data yang Anda cari, tetapi sebenarnya itu tidak dapat digantikan dengan contoh lain selain yang Anda buat. Apa yang sebenarnya ingin Anda lakukan adalah membuat antarmuka / kelas Anda sendiri yang merupakan bagian pertama Anda buat dan bagian kedua Anda konsumsi. Ini dapat membungkus LinkedHashMap "asli", dan menyediakan pengambil Peta atau mengimplementasikan antarmuka Peta.

Ini sedikit berbeda dari jawaban CandiedOrange, karena saya akan merekomendasikan merangkum Peta asli (dan mendelegasikan panggilan ke sana sesuai kebutuhan) daripada memperpanjangnya. Kadang-kadang ini adalah salah satu perang suci gaya, tetapi jelas bagi saya itu bukan "Peta dengan beberapa hal tambahan", melainkan "Tas saya berisi informasi berguna negara, yang secara internal dapat saya wakili dengan Peta".

Jika Anda memiliki dua variabel yang harus Anda lewati seperti ini, Anda mungkin telah membuat kelas untuk itu tanpa berpikir banyak tentangnya. Tetapi kadang-kadang berguna untuk memiliki kelas bahkan jika itu hanya satu variabel anggota, hanya karena itu hal yang sama secara logis, bukan "nilai" tetapi "hasil operasi saya bahwa saya perlu melakukan sesuatu dengan nanti".


Aku seperti pemikiran ini - saya telah ada :) MyBagOfUsefulInformationakan memerlukan metode (atau konstruktor) untuk mengisi itu: MyBagOfUsefulInformation.populate(SomeType data). Tetapi dataperlu hasil pencarian yang diurutkan. Jadi apa jadinya SomeType, jika tidak LinkedHashMap? Saya tidak yakin saya dapat memecahkan Catch 22 ini.
Vidar S. Ramdal

Mengapa tidak MyBagOfUsefulInformationdapat dibuat oleh DAO atau apa pun yang menghasilkan data di sistem Anda? Mengapa Anda perlu memaparkan peta yang mendasari sama sekali ke seluruh kode Anda di luar produsen dan konsumen Tas?

Bergantung pada arsitektur Anda, Anda mungkin dapat menggunakan konstruktor pribadi / terlindungi / hanya-paket untuk memastikan bahwa objek hanya dapat dibuat oleh produsen yang Anda inginkan. Atau Anda mungkin hanya perlu melakukannya sebagai konvensi, bahwa itu hanya dapat dibuat oleh "pabrik" yang tepat.

Ya, saya akhirnya melakukan sesuatu yang serupa, dengan mengirimkan MyBagOfUsefulInformationsebagai parameter pada metode DAO: softwareengineering.stackexchange.com/a/360079/52573
Vidar S. Ramdal

4

LinkedHashMap adalah satu-satunya peta java yang memiliki fitur urutan penyisipan yang Anda cari. Jadi membuang Prinsip Pembalikan Ketergantungan itu menggoda dan bahkan mungkin praktis. Pertama, pertimbangkan apa yang harus dilakukan untuk mengikutinya. Inilah yang SOLID akan minta Anda lakukan.

Catatan: ganti nama Ramdaldengan nama deskriptif yang mengomunikasikan bahwa konsumen antarmuka ini adalah pemilik antarmuka ini. Yang menjadikannya otoritas yang memutuskan apakah urutan penyisipan penting. Jika Anda hanya menyebut ini, InsertionOrderMapAnda benar-benar melewatkan intinya.

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);

Apakah ini desain besar di depan? Mungkin, tergantung pada seberapa besar kemungkinan Anda berpikir bahwa Anda akan memerlukan implementasi selain itu LinkedHashMap. Tetapi jika Anda tidak mengikuti DIP hanya karena itu akan sangat menyakitkan, saya tidak berpikir pelat ketel lebih menyakitkan dari ini. Ini adalah pola yang saya gunakan ketika saya berharap kode yang tidak tersentuh mengimplementasikan antarmuka yang tidak. Bagian yang paling menyakitkan adalah memikirkan nama-nama baik.


2
Saya suka penamaannya!
Vidar S. Ramdal

1

Terima kasih atas banyak saran dan makanan yang bagus untuk dipikirkan.

Saya akhirnya memperluas membuat kelas peta baru, membuat processDatametode contoh:

class DataMap extends LinkedHashMap<Key, Value> {

   processData();

}

Lalu saya refactored metode DAO sehingga tidak mengembalikan peta, tetapi mengambil targetpeta sebagai parameter:

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

Jadi mengisi DataMapdan memproses data sekarang merupakan proses dua langkah, yang baik-baik saja, karena ada beberapa variabel lain yang merupakan bagian dari algoritma, yang berasal dari tempat lain.

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

Ini memungkinkan implementasi Peta saya untuk mengontrol bagaimana entri dimasukkan ke dalamnya, dan menyembunyikan persyaratan pemesanan - sekarang detail implementasi DataMap.


0

Jika Anda ingin berkomunikasi bahwa struktur data yang Anda gunakan ada karena suatu alasan, tambahkan komentar di atas tanda tangan metode. Jika pengembang lain di masa depan menemukan garis kode ini dan memperhatikan peringatan alat, mereka mungkin memperhatikan komentar itu juga dan menahan diri dari "memperbaiki" masalah tersebut. Jika tidak ada komentar, maka tidak ada yang akan menghentikan mereka untuk mengubah tanda tangan.

Menekan peringatan lebih rendah daripada berkomentar dalam pendapat saya, karena penindasan itu sendiri tidak menyatakan alasan mengapa peringatan itu ditekan. Kombinasi penindasan peringatan dan komentar juga akan baik-baik saja.


0

Jadi, izinkan saya mencoba memahami konteks Anda di sini:

... urutan penyisipan penting ... Menyortir peta akan menjadi operasi yang berat ...

... hasil kueri sudah disortir seperti yang saya inginkan

Sekarang, apa yang sedang Anda lakukan:

Saya mengambil satu set tupel dari basis data, dan memasukkannya ke dalam peta ...

Dan inilah kode Anda saat ini:

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

Saran saya adalah melakukan hal berikut:

  • Gunakan injeksi dependensi dan suntikkan beberapa MyTupleRepository ke dalam metode pemrosesan (MyTupleRepository adalah antarmuka yang diimplementasikan oleh objek yang mengambil objek tuple Anda, biasanya dari DB);
  • secara internal ke metode pemrosesan, letakkan data dari repositori (alias DB, yang sudah mengembalikan data yang dipesan) dalam koleksi LinkedHashMap tertentu, karena ini adalah detail internal dari algoritma pemrosesan (karena itu tergantung pada bagaimana data tersebut diatur dalam struktur data );
  • Perhatikan bahwa, ini cukup banyak apa yang sudah Anda lakukan, tetapi dalam hal ini ini akan dilakukan dalam metode pemrosesan. Repositori Anda dipakai di tempat lain (Anda sudah memiliki kelas yang mengembalikan data, ini adalah repositori dalam contoh ini)

Contoh Kode

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...
    ...
}

Saya kira ini akan menghilangkan peringatan Sonar, dan juga menentukan tata letak khusus data yang diperlukan oleh metode pemrosesan.


Hmm, tapi bagaimana repositori akan dipakai? Bukankah ini hanya memindahkan masalah ke tempat lain (ke tempat MyTupleRepositorydibuat?)
Vidar S. Ramdal

Saya pikir saya akan mengalami masalah yang sama dengan jawaban Peter Cooper .
Vidar S. Ramdal

Saran saya melibatkan penerapan Prinsip Injeksi Ketergantungan; dalam contoh ini; MyTupleRepository adalah antarmuka yang mendefinisikan kemampuan mengambil tupel yang Anda sebutkan (yang meminta DB). Di sini, Anda menyuntikkan objek ini ke dalam metode pemrosesan. Anda sudah memiliki beberapa kelas yang mengembalikan data; ini hanya mengabstraksi dalam antarmuka, dan Anda menyuntikkan objek ke dalam metode 'processData', yang secara internal menggunakan LinkedHashMap karena ini secara intrinsik merupakan bagian dari pemrosesan.
Emerson Cardoso

Saya mengedit jawaban saya, berusaha lebih jelas tentang apa yang saya sarankan.
Emerson Cardoso

-1

Pertanyaan ini sebenarnya adalah banyak masalah dengan model data Anda digulung menjadi satu. Anda harus mulai melepaskan mereka, satu per satu. Solusi yang lebih alami dan intuitif akan keluar saat Anda mencoba menyederhanakan setiap bagian teka-teki.

Masalah 1: Anda tidak dapat bergantung pada Pesanan DB

Deskripsi Anda tentang pengurutan data Anda tidak jelas.

  • Masalah potensial terbesar adalah bahwa Anda tidak menentukan jenis eksplisit dalam database Anda, melalui ORDER BYklausa. Jika bukan karena sepertinya terlalu mahal, program Anda memiliki bug . Database diizinkan untuk mengembalikan hasil dalam urutan apa pun jika Anda tidak menentukannya; Anda tidak dapat bergantung padanya secara acak mengembalikan data dalam urutan hanya karena Anda menjalankan kueri beberapa kali dan terlihat seperti itu. Urutan mungkin berubah karena baris disusun ulang pada disk, atau beberapa dihapus dan yang baru menggantikannya, atau indeks ditambahkan. Anda harus menentukan ORDER BYklausa dari beberapa jenis. Kecepatan tidak ada artinya tanpa kebenaran.
  • Juga tidak jelas apa yang Anda maksud dengan penyisipan urutan penyisipan. Jika Anda berbicara tentang database itu sendiri, Anda harus memiliki kolom yang benar-benar melacak ini, dan itu harus dimasukkan dalam ORDER BYklausa Anda . Kalau tidak, Anda memiliki bug. Jika kolom seperti itu belum ada, maka Anda perlu menambahkannya. Opsi khas untuk kolom seperti ini adalah kolom cap waktu penyisipan atau kunci penambahan otomatis. Kunci peningkatan otomatis lebih dapat diandalkan.

Masalah 2: Membuat memori menjadi efisien

Setelah Anda memastikan itu dijamin akan mengembalikan data dalam urutan yang Anda harapkan, Anda dapat memanfaatkan fakta ini untuk membuat jenis memori jauh lebih efisien. Cukup tambahkan kolom row_number()ataudense_rank() (atau setara dengan basis data Anda) ke set hasil kueri Anda. Sekarang setiap baris memiliki indeks yang akan memberi Anda indikasi langsung tentang urutan seharusnya, dan Anda dapat mengurutkannya dalam memori dengan mudah. Pastikan Anda memberi indeks nama yang bermakna (seperti sortedBySomethingIndex).

Biola. Sekarang Anda tidak perlu lagi bergantung pada urutan hasil basis data.

Masalah 3: Apakah Anda bahkan perlu melakukan pemrosesan kode ini?

SQL sebenarnya sangat kuat. Ini adalah bahasa deklaratif luar biasa yang memungkinkan Anda melakukan banyak transformasi dan agregasi pada data Anda. Sebagian besar DB bahkan mendukung operasi lintas baris saat ini. Mereka disebut fungsi jendela atau analitik:

Apakah Anda bahkan perlu menarik data Anda ke dalam memori seperti ini? Atau bisakah Anda melakukan semua pekerjaan dalam kueri SQL dengan menggunakan fungsi jendela? Jika Anda dapat melakukan semua (atau bahkan mungkin hanya bagian penting) dari pekerjaan di DB, fantastis! Masalah kode Anda hilang (atau menjadi lebih sederhana)!

Masalah 4: Anda melakukan apa untuk itu data?

Dengan asumsi Anda tidak dapat melakukan semuanya dalam DB, biarkan saya meluruskan ini. Anda mengambil data sebagai peta (yang dikunci oleh hal-hal yang tidak ingin Anda urutkan berdasarkan), lalu Anda mengulanginya dengan urutan penyisipan , dan memodifikasi peta dengan mengganti nilai beberapa kunci dan menambahkan yang baru?

Maaf, tapi apa-apaan ini?

Penelepon seharusnya tidak perlu khawatir tentang semua ini . Sistem yang Anda buat sangat rapuh. Hanya perlu satu kesalahan bodoh (bahkan mungkin dibuat sendiri, seperti yang telah kita semua lakukan) untuk membuat satu perubahan kecil yang salah dan semuanya runtuh seperti setumpuk kartu.

Ini mungkin ide yang lebih baik:

  • Apakah fungsi Anda menerima a List.
  • Ada beberapa cara untuk menangani masalah pemesanan.
    1. Terapkan Gagal Cepat. Lempar kesalahan jika daftar tidak sesuai dengan urutan fungsi yang disyaratkan. (Catatan: Anda dapat menggunakan indeks pengurutan dari Masalah 2 untuk mengetahui apakah itu benar.)
    2. Buat salinan yang diurutkan sendiri (lagi menggunakan indeks dari masalah 2).
    3. Mencari cara untuk membangun peta itu sendiri secara berurutan.
  • Buat peta yang Anda butuhkan secara internal untuk fungsi tersebut, sehingga penelepon tidak perlu mempedulikannya.
  • Sekarang ulangi apa pun dalam rangka representasi yang Anda miliki dan lakukan apa yang harus Anda lakukan.
  • Kembalikan peta, atau ubah menjadi nilai pengembalian yang sesuai

Variasi yang mungkin bisa berupa membangun representasi yang diurutkan dan kemudian membuat peta kunci untuk diindeks . Ini akan memungkinkan Anda memodifikasi salinan yang disortir di tempatnya, tanpa sengaja membuat duplikat.

Atau mungkin ini lebih masuk akal: singkirkan dataparameternya dan buat processDatabenar - benar mengambil datanya sendiri. Anda kemudian dapat mendokumentasikan bahwa Anda melakukan ini karena memiliki persyaratan yang sangat spesifik tentang cara pengambilan data. Dengan kata lain, buat fungsi memiliki seluruh proses, bukan hanya satu bagian saja; inter-dependensi terlalu kuat untuk membagi logika menjadi potongan yang lebih kecil. (Ubah nama fungsi dalam proses.)

Mungkin ini tidak akan berhasil untuk situasi Anda. Saya tidak tahu tanpa detail lengkap masalah. Tapi saya tahu desain yang rapuh dan membingungkan ketika saya mendengarnya.

Ringkasan

Saya pikir masalah di sini pada akhirnya adalah bahwa setan ada dalam perinciannya. Ketika saya mulai mengalami masalah seperti ini, biasanya karena saya memiliki representasi data saya yang tidak sesuai untuk masalah yang saya coba selesaikan. Solusi terbaik adalah menemukan representasi yang lebih baik , dan kemudian masalah saya menjadi sederhana (mungkin tidak mudah, tetapi langsung) untuk dipecahkan.

Temukan seseorang yang mendapatkan poin itu: pekerjaan Anda adalah mengurangi masalah Anda menjadi serangkaian masalah yang sederhana dan langsung. Kemudian Anda dapat membuat kode yang kuat dan intuitif. Bicaralah pada mereka. Kode yang bagus dan desain yang bagus membuat Anda berpikir bahwa ada orang idiot yang bisa memikirkannya, karena mereka sederhana dan mudah. Mungkin ada pengembang senior yang memiliki pola pikir yang bisa Anda ajak bicara.


"Apa maksudmu tidak ada urutan alami tetapi masalah urutan penyisipan? Apakah Anda mengatakan bahwa itu penting urutan data dimasukkan ke dalam tabel DB, tetapi Anda tidak memiliki kolom yang dapat memberi tahu Anda urutan barang apa yang dimasukkan?" - pertanyaannya menyatakan ini: "Mengurutkan peta akan menjadi operasi yang berat, jadi saya ingin menghindari melakukan itu, mengingat bahwa hasil kueri sudah diurutkan". Ini jelas berarti bahwa ada adalah perintah yang pasti calculatable untuk data, karena jika tidak menyortir mustahil daripada berat, tapi itu agar didefinisikan berbeda dengan tatanan alam tombol.
Jules

2
Dengan kata lain, OP bekerja pada hasil permintaan seperti select key, value from table where ... order by othercolumn, dan perlu mempertahankan pemesanan dalam pemrosesan mereka. Urutan penyisipan yang mereka maksudkan adalah urutan penyisipan ke dalam peta mereka , ditentukan oleh urutan yang digunakan dalam kueri mereka, bukan urutan penyisipan ke dalam basis data . Hal ini diperjelas oleh penggunaan LinkedHashMap, yang merupakan struktur data yang memiliki karakteristik baik dari Mapdan dari Listpasangan kunci-nilai.
Jules

@ Jules saya akan membersihkan bagian itu sedikit, terima kasih. (Saya benar-benar ingat membaca itu, tetapi ketika saya memeriksa hal-hal saat menulis pertanyaan, saya tidak dapat menemukannya. Lol. Terlalu banyak dalam rumput liar.) Tetapi pertanyaannya tidak jelas tentang apa yang mereka lakukan dengan DB permintaan dan apakah mereka memiliki jenis yang eksplisit atau tidak. Mereka juga mengatakan bahwa "urutan penyisipan penting." Intinya adalah bahwa meskipun penyortiran itu berat, Anda tidak dapat mengandalkan DB untuk hanya memesan secara ajaib jika Anda tidak mengatakannya secara eksplisit. Dan jika Anda sedang melakukannya di DB, maka Anda dapat menggunakan "index" untuk membuatnya efisien dalam kode.
jpmc26

* menulis jawabannya (Methinks saya harus segera pergi tidur.)
jpmc26

Ya, @ Jules benar. Ada adalah sebuah order byklausul dalam query, tetapi non-sepele ( tidak hanya order by column), jadi saya ingin menghindari reimplementing penyortiran di Jawa. Meskipun SQL sangat kuat (dan kita berbicara tentang database Oracle 11g di sini), sifat processDataalgoritme membuatnya lebih mudah untuk diekspresikan di Jawa. Dan ya, "urutan penyisipan" berarti " urutan penyisipan peta ", yaitu urutan hasil kueri.
Vidar S. Ramdal
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.