จะสื่อสารลำดับการแทรกนั้นสำคัญอย่างไรในแผนที่?


24

ฉันกำลังดึงชุดของสิ่งอันดับจากฐานข้อมูลและวางลงในแผนที่ แบบสอบถามฐานข้อมูลมีราคาแพง

ไม่มีการจัดเรียงองค์ประกอบตามธรรมชาติที่เห็นได้ชัดในแผนที่ แต่ลำดับการแทรกยังคงสำคัญ การเรียงลำดับแผนที่จะเป็นการดำเนินการที่หนักหน่วงดังนั้นฉันต้องการหลีกเลี่ยงการทำเช่นนั้นเนื่องจากผลลัพธ์แบบสอบถามนั้นได้เรียงลำดับตามที่ฉันต้องการแล้ว ดังนั้นฉันเพิ่งเก็บผลลัพธ์แบบสอบถามลงในLinkedHashMapและส่งคืนแผนที่จากวิธี DAO:

public LinkedHashMap<Key, Value> fetchData()

ฉันมีวิธีprocessDataที่ควรทำการประมวลผลบนแผนที่ - แก้ไขค่าบางอย่างเพิ่มคีย์ / ค่าใหม่ มันถูกกำหนดให้เป็น

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

อย่างไรก็ตาม linters หลายตัว (Sonar ฯลฯ ) บ่นว่าประเภทของ 'data' ควรเป็นส่วนต่อประสานเช่น 'Map' แทนที่จะใช้ "LinkedHashMap" ( squid S1319 )
โดยพื้นฐานแล้วมันบอกว่าฉันควรจะมี

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

แต่ฉันต้องการให้ลายเซ็นของวิธีการบอกว่าลำดับของแผนที่มีความสำคัญกับอัลกอริธึมprocessDataเพื่อที่ว่าวิธีการของฉันจะไม่ผ่านแผนที่แบบสุ่มใด ๆ

ฉันไม่ต้องการใช้SortedMapเพราะ (จากjavadoc ของjava.util.SortedMap ) "ถูกจัดเรียงตามลำดับตามธรรมชาติของปุ่มของมันหรือโดยComparator ที่มีให้ตามปกติในการสร้างแผนที่เรียงลำดับ"

กุญแจของฉันไม่มีการเรียงลำดับที่เป็นธรรมชาติและการสร้างเครื่องมือเปรียบเทียบเพื่อไม่ทำอะไรเลยดูเหมือนว่าละเอียด

และฉันยังคงอยากให้มันเป็นแผนที่จะใช้ประโยชน์จากputการหลีกเลี่ยงการคีย์ที่ซ้ำกันและอื่น ๆ ถ้าไม่ได้ที่จะได้รับdataList<Map.Entry<Key, Value>>

ดังนั้นฉันจะบอกว่าวิธีการของฉันต้องการแผนที่ที่เรียงลำดับแล้ว ? น่าเสียดายที่ไม่มีjava.util.LinkedMapส่วนต่อประสานหรือฉันจะใช้มัน

คำตอบ:


56

LinkedHashMapดังนั้นการใช้งาน

ใช่คุณควรใช้Mapมากกว่าการดำเนินการเฉพาะเมื่อใดก็ตามที่เป็นไปได้และใช่นี้เป็นวิธีที่ดีที่สุด

ที่กล่าวว่านี่เป็นสถานการณ์ที่แปลกประหลาดที่การใช้งานMapจริงมีความสำคัญ สิ่งนี้จะไม่เป็นจริงสำหรับ 99.9% ของคดีในรหัสของคุณเมื่อคุณใช้Mapและยังอยู่ที่นี่ในสถานการณ์ 0.1% นี้ โซนาร์ไม่สามารถรู้เรื่องนี้ได้ดังนั้น Sonar จึงบอกให้คุณหลีกเลี่ยงการใช้งานเฉพาะเพราะจะถูกต้องในกรณีส่วนใหญ่

ฉันจะโต้แย้งว่าหากคุณสามารถสร้างกรณีสำหรับการใช้งานเฉพาะอย่าพยายามใส่ลิปสติกลงบนหมู คุณต้องไม่ได้ LinkedHashMapMap

สิ่งนี้กล่าวว่าหากคุณยังใหม่กับการเขียนโปรแกรมและสะดุดกับคำตอบนี้อย่าคิดว่าสิ่งนี้จะช่วยให้คุณต่อต้านแนวปฏิบัติที่ดีที่สุดได้ แต่เมื่อแทนที่การดำเนินการหนึ่งสำหรับอีกรายการหนึ่งไม่เป็นที่ยอมรับสิ่งเดียวที่คุณทำได้คือใช้การใช้งานเฉพาะนั้นและถูกสาปแช่งกับ Sonar


1
วิธีการปฏิบัติซึ่งฉันชอบ
Vidar S. Ramdal

20
ฉันเห็นด้วยกับคำตอบเกือบทั้งหมด ฉันแค่จะบอกว่าคุณไม่ได้สาปแช่ง Sonar คุณสามารถกำหนดค่าให้ละเว้นข้อผิดพลาด / คำเตือนนั้น ๆ ได้เสมอ ดู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.- คำแนะนำที่ดีหากมีสิ่งใดสิ่งหนึ่งเช่น "แนวปฏิบัติที่ดีที่สุด" คำแนะนำที่ดีกว่า: เรียนรู้วิธีการตัดสินใจที่ถูกต้อง ทำตามแบบฝึกหัดหากเหมาะสม แต่ให้เครื่องมือและเจ้าหน้าที่แนะนำกระบวนการคิดของคุณไม่ใช่สั่งการ
Robert Harvey

13
หมายเหตุ: เมื่อโซนาร์รายงานบางสิ่งให้คุณคุณสามารถปิดเป็น "ไม่สามารถแก้ไข" และออกจากบันทึกได้ว่าทำไมคุณถึงไม่ทำ เช่นโซนาร์ไม่เพียง แต่จะหยุดรบกวนคุณ แต่คุณจะมีร่องรอยของสาเหตุที่คุณทำอย่างนั้น
Walfrat

2
ฉันคิดว่าสิ่งที่ทำให้สิ่งนี้เป็นข้อยกเว้นสำหรับหลักการทั่วไปคือ LinkedHashMap มีสัญญาที่เฉพาะเจาะจงกับการนำไปใช้นั้นและไม่ได้แสดงในอินเตอร์เฟสใด ๆ นี่ไม่ใช่กรณีปกติ ดังนั้นวิธีเดียวที่จะแสดงความเชื่อมั่นในสัญญานั้นคือการใช้ประเภทการนำไปใช้งาน
Dana

21

คุณกำลังต่อสู้สามสิ่ง:

อันดับแรกคือไลบรารีคอนเทนเนอร์ของ Java ไม่มีสิ่งใดในอนุกรมวิธานของมันที่ช่วยให้คุณสามารถกำหนดได้ว่าคลาสจะวนซ้ำตามลำดับที่คาดเดาได้หรือไม่ ไม่มีIteratesInInsertedOrderMapอินเทอร์เฟซที่สามารถใช้งานได้LinkedHashMapซึ่งทำให้การตรวจสอบประเภท (และการใช้งานการใช้งานทางเลือกที่ทำงานในลักษณะเดียวกัน) เป็นไปไม่ได้ อาจเป็นเพราะการออกแบบเพราะวิญญาณของมันคือคุณควรจะสามารถจัดการกับวัตถุที่มีพฤติกรรมเหมือนนามธรรมMapได้

ข้อที่สองคือความเชื่อที่ว่าสิ่งที่ผู้ให้สัมภาษณ์บอกว่าจะต้องได้รับการปฏิบัติในฐานะพระกิตติคุณและการเพิกเฉยต่อสิ่งที่กล่าวมานั้นไม่ดี ในทางตรงกันข้ามกับสิ่งที่ผ่านไปแล้วสำหรับการฝึกฝนที่ดีในวันนี้คำเตือนของ linter ไม่ควรเป็นอุปสรรคในการเรียกรหัสของคุณได้ดี พวกเขาจะพร้อมท์ให้เหตุผลเกี่ยวกับรหัสที่คุณเขียนและใช้ประสบการณ์และการตัดสินของคุณเพื่อตัดสินว่าคำเตือนนั้นมีเหตุผลหรือไม่ คำเตือนที่ไม่ยุติธรรมเป็นสาเหตุที่เกือบทุกเครื่องมือวิเคราะห์แบบคงที่มีกลไกที่จะบอกว่าคุณตรวจสอบรหัสแล้วคุณคิดว่าสิ่งที่คุณทำอยู่นั้นไม่เป็นไรและพวกเขาไม่ควรบ่นในอนาคต

ประการที่สามและนี่อาจเป็นเนื้อของมันLinkedHashMapอาจเป็นเครื่องมือที่ผิดสำหรับงาน แผนที่มีไว้สำหรับการเข้าถึงแบบสุ่มและไม่ได้รับคำสั่ง หากprocessData()เพียง iterates กว่าระเบียนในการสั่งซื้อและไม่ต้องไปหาข้อมูลอื่น ๆ โดยคีย์คุณบังคับให้การใช้งานที่เฉพาะเจาะจงของการทำงานของการที่Map Listในทางกลับกันหากคุณต้องการทั้งสองอย่างLinkedHashMapเป็นเครื่องมือที่เหมาะสมเพราะเป็นที่รู้กันว่าทำสิ่งที่คุณต้องการและคุณเป็นมากกว่าการพิสูจน์ว่าเป็นสิ่งจำเป็น


2
"LinkedHashMap อาจเป็นเครื่องมือที่ผิดสำหรับงาน" ใช่อาจจะ. เมื่อฉันบอกว่าฉันต้องการฉันจะเพียงเช่นกันกล่าวว่าOrderedMap UniqueListตราบใดที่มันเป็นคอลเล็กชันที่มีลำดับการทำซ้ำที่กำหนดไว้จะแทนที่การทำซ้ำในส่วนแทรก
Vidar S. Ramdal

2
@ VidarS.Ramdal แบบสอบถามฐานข้อมูลจะเป็นสถานที่ที่เหมาะสำหรับการคัดลอกรายการที่ซ้ำกัน หากฐานข้อมูลของคุณไม่สามารถทำเช่นนั้นคุณสามารถเก็บSetคีย์ชั่วคราวไว้เสมอในขณะที่คุณกำลังสร้างรายการเพื่อหาจุด
Blrfl

โอ้ฉันเห็นว่าฉันทำให้เกิดความสับสน ใช่ผลการสืบค้นฐานข้อมูลไม่มีข้อมูลที่ซ้ำกัน แต่processDataปรับเปลี่ยนแผนที่แทนที่ค่าบางค่าแนะนำคีย์ / ค่าใหม่บางอย่าง ดังนั้นสามารถนำรายการที่ซ้ำกันถ้ามันเป็นปฏิบัติการในบางสิ่งบางอย่างอื่นที่ไม่ใช่processData Map
Vidar S. Ramdal

7
@ VidarS.Ramdal: ดูเหมือนคุณจะต้องเขียนของคุณเองUniqueList(หรือOrderedUniqueList) และใช้มัน มันค่อนข้างง่ายและทำให้การใช้งานของคุณชัดเจนขึ้น
TMN

2
@ TMN ใช่ฉันเริ่มคิดไปในทิศทางนั้นแล้ว หากคุณต้องการโพสต์ข้อเสนอแนะของคุณเป็นคำตอบแน่นอนมันจะได้รับ upvote ของฉัน
Vidar S. Ramdal

15

หากสิ่งที่คุณจะได้รับจากLinkedHashMapความสามารถในการเขียนทับซ้ำกัน แต่คุณจริงๆใช้มันเป็นListแล้วผมขอแนะนำให้มันจะดีกว่าที่จะสื่อสารกับการใช้งานที่คุณกำหนดเองListการดำเนินงาน คุณสามารถใช้มันกับคลาสคอลเลกชัน Java ที่มีอยู่และเพียงแค่แทนที่ใด ๆaddและremoveวิธีการในการปรับปรุงการจัดเก็บสำรองของคุณและติดตามกุญแจเพื่อให้แน่ใจว่าไม่ซ้ำกัน การให้ชื่อที่โดดเด่นเช่นProcessingListนี้จะทำให้ชัดเจนว่าข้อโต้แย้งที่นำเสนอในprocessDataวิธีการของคุณจะต้องได้รับการจัดการในวิธีการเฉพาะ


5
นี่อาจเป็นความคิดที่ดีอยู่ดี เฮ้คุณสามารถมีไฟล์หนึ่งบรรทัดที่สร้างProcessingListเป็นนามแฝงได้LinkedHashMapคุณสามารถตัดสินใจที่จะแทนที่มันด้วยอย่างอื่นในภายหลังตราบใดที่คุณยังคงอินเทอร์เฟซสาธารณะไม่บุบสลาย
CompuChip

11

ฉันได้ยินคุณพูดว่า "ฉันมีส่วนหนึ่งของระบบของฉันที่สร้าง LinkedHashMap และในอีกส่วนหนึ่งของระบบของฉันฉันต้องยอมรับเฉพาะวัตถุ LinkedHashMap ที่ผลิตโดยส่วนแรกเนื่องจากส่วนที่ผลิตโดยกระบวนการอื่นชนะ ' ทำงานไม่ถูกต้อง "

นั่นทำให้ฉันคิดว่าปัญหาที่นี่คือที่จริงแล้วคุณกำลังพยายามใช้ LinkedHashMap เพราะส่วนใหญ่จะเหมาะกับข้อมูลที่คุณกำลังมองหา แต่อันที่จริงแล้วมันไม่สามารถทดแทนได้ด้วยอินสแตนซ์อื่นนอกเหนือจากที่คุณสร้างขึ้น สิ่งที่คุณต้องการทำจริง ๆ ก็คือสร้างส่วนต่อประสาน / คลาสของคุณเองซึ่งเป็นสิ่งที่ส่วนแรกของคุณสร้างขึ้นและส่วนที่สองของคุณจะสิ้นเปลือง มันสามารถห่อ "จริง" LinkedHashMap และให้ Map getter หรือใช้อินเทอร์เฟซแผนที่

นี่เป็นข้อแตกต่างเล็กน้อยจากคำตอบของ CandiedOrange ซึ่งฉันขอแนะนำให้ใส่ในแผนที่จริง (และมอบหมายการโทรตามความจำเป็น) แทนที่จะขยายออก บางครั้งมันเป็นหนึ่งในสงครามศักดิ์สิทธิ์ในรูปแบบเหล่านั้น แต่มันฟังดูดีสำหรับฉันว่าไม่ใช่ "แผนที่ที่มีสิ่งเพิ่มเติม" คือ "กระเป๋าข้อมูลรัฐที่มีประโยชน์ของฉันซึ่งฉันอาจเป็นตัวแทนของแผนที่"

หากคุณมีตัวแปรสองตัวที่คุณต้องผ่านมันไปแบบนี้คุณอาจจะทำคลาสให้โดยไม่ต้องคิดมาก แต่บางครั้งมันก็มีประโยชน์ที่จะมีคลาสแม้ว่ามันจะเป็นเพียงตัวแปรสมาชิกเพียงอย่างเดียวเพราะมันมีเหตุผลเหมือนกันไม่ใช่ "คุณค่า" แต่ "ผลลัพธ์ของการดำเนินการของฉันที่ฉันต้องทำในภายหลัง"


ผมชอบความคิดนี้ - ผมได้มี :) MyBagOfUsefulInformationจะต้องมีวิธีการ (หรือคอนสตรัค) MyBagOfUsefulInformation.populate(SomeType data)เพื่อเติมมัน: แต่dataจะต้องเป็นผลลัพธ์แบบสอบถามที่เรียงลำดับ ดังนั้นสิ่งที่จะSomeTypeเป็นไปได้หากไม่ได้LinkedHashMap? ฉันไม่แน่ใจว่าฉันสามารถทำลายสิ่งที่จับได้ 22.
Vidar S. Ramdal

เหตุใดจึงไม่MyBagOfUsefulInformationสามารถสร้างโดย DAO หรืออะไรก็ตามที่สร้างข้อมูลในระบบของคุณ ทำไมคุณต้องเปิดเผยแผนที่พื้นฐานไปยังส่วนที่เหลือของรหัสของคุณนอกผู้ผลิตและผู้บริโภคของกระเป๋า?

ขึ้นอยู่กับสถาปัตยกรรมของคุณคุณอาจใช้ constructor ส่วนตัว / ป้องกัน / แพ็คเกจเท่านั้นเพื่อบังคับใช้ว่าผู้สร้างที่คุณต้องการสร้างสามารถสร้างได้เท่านั้น หรือคุณอาจต้องทำตามแบบแผนซึ่งสามารถสร้างได้โดย "โรงงาน" ที่ถูกต้องเท่านั้น

ใช่ฉันลงเอยด้วยการทำบางสิ่งที่คล้ายกันโดยส่งผ่านMyBagOfUsefulInformationพารามิเตอร์ไปยังวิธีการ DAO: softwareengineering.stackexchange.com/a/360079/52573
Vidar S. Ramdal

4

LinkedHashMap เป็นแผนที่ java เดียวที่มีคุณสมบัติการแทรกคำสั่งที่คุณกำลังมองหา ดังนั้นการทิ้งหลักการผกผันของการพึ่งพาอาศัยนั้นเป็นที่ดึงดูดและอาจเป็นไปได้ ก่อนอื่นให้พิจารณาสิ่งที่จะต้องปฏิบัติตาม นี่คือสิ่งที่SOLIDจะขอให้คุณทำ

หมายเหตุ: แทนที่ชื่อRamdalด้วยชื่อที่สื่อความหมายซึ่งสื่อสารว่าคอนซูมเมอร์ของอินเตอร์เฟสนี้เป็นเจ้าของอินเตอร์เฟสนี้ ซึ่งทำให้สิทธิ์ในการตัดสินใจว่าลำดับการแทรกเป็นสิ่งสำคัญหรือไม่ ถ้าคุณเรียกสิ่งนี้InsertionOrderMapว่าคุณพลาดจุดนี้จริงๆ

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

นี่เป็นการออกแบบครั้งใหญ่หรือไม่? LinkedHashMapอาจจะขึ้นอยู่กับวิธีการที่มีแนวโน้มที่คุณคิดว่ามันคือการที่คุณเคยจะต้องมีการใช้งานนอกเหนือจากการ แต่ถ้าคุณไม่ได้ทำตาม DIP เพียงเพราะมันจะเจ็บปวดมากฉันไม่คิดว่าแผ่นหม้อไอน้ำจะเจ็บปวดกว่านี้อีก นี่คือรูปแบบที่ฉันใช้เมื่อฉันต้องการให้รหัสที่ไม่สามารถแตะต้องได้นั้นใช้อินเทอร์เฟซที่ไม่มี ส่วนที่เจ็บปวดที่สุดคือการคิดถึงชื่อที่ดี


2
ฉันชอบการตั้งชื่อ!
Vidar S. Ramdal

1

ขอบคุณสำหรับคำแนะนำที่ดีและอาหารสำหรับความคิด

ฉันสิ้นสุดการขยายการสร้างคลาสแผนที่ใหม่สร้างprocessDataเมธอดอินสแตนซ์:

class DataMap extends LinkedHashMap<Key, Value> {

   processData();

}

จากนั้นฉันปรับโครงสร้างวิธี DAO ใหม่เพื่อไม่ให้ส่งคืนแผนที่ แต่ใช้targetแผนที่เป็นพารามิเตอร์แทน:

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

ดังนั้นการเติมข้อมูลDataMapและประมวลผลข้อมูลจึงเป็นกระบวนการสองขั้นตอนซึ่งใช้ได้เนื่องจากมีตัวแปรอื่น ๆ ที่เป็นส่วนหนึ่งของอัลกอริทึมซึ่งมาจากที่อื่น

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

นี้จะช่วยให้การดำเนินงานแผนที่ของฉันที่จะควบคุมว่ารายการที่จะแทรกเข้าไปในมันและหนังออกไปความต้องการสั่งซื้อ - DataMapตอนนี้มันเป็นรายละเอียดการดำเนินงานของ


0

หากคุณต้องการสื่อสารว่าโครงสร้างข้อมูลที่คุณใช้นั้นมีเหตุผลให้เพิ่มความคิดเห็นไว้เหนือลายเซ็นของวิธีการ หากนักพัฒนาซอฟต์แวร์รายอื่นในอนาคตพบกับโค้ดนี้และสังเกตเห็นคำเตือนเครื่องมือพวกเขาอาจสังเกตเห็นความคิดเห็นด้วยและงดเว้นจาก "แก้ไข" ปัญหา หากไม่มีความคิดเห็นแล้วจะไม่มีอะไรหยุดพวกเขาจากการเปลี่ยนลายเซ็น

การยับยั้งการเตือนนั้นด้อยไปกว่าการแสดงความคิดเห็นในความคิดเห็นของฉันเพราะการปราบปรามนั้นไม่ได้ระบุเหตุผลว่าทำไมการเตือนจึงถูกระงับ การรวมกันของการปราบปรามการเตือนและความคิดเห็นจะดีเช่นกัน


0

ดังนั้นให้ฉันพยายามที่จะเข้าใจบริบทของคุณที่นี่:

... ลำดับการแทรกสำคัญ ... การเรียงลำดับแผนที่จะเป็นการใช้งานที่หนักหน่วง

... ผลการสืบค้นเรียงลำดับแล้วตามที่ฉันต้องการ

ตอนนี้สิ่งที่คุณกำลังทำอยู่:

ฉันดึงชุดของ tuples จากฐานข้อมูลและวางลงในแผนที่ ...

และนี่คือรหัสปัจจุบันของคุณ:

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

คำแนะนำของฉันคือทำดังต่อไปนี้:

  • ใช้การฉีดพึ่งพาและฉีด MyTupleRepository บางอย่างลงในวิธีการประมวลผล (MyTupleRepository เป็นอินเทอร์เฟซที่นำมาใช้โดยวัตถุที่ดึงวัตถุ tuple ของคุณซึ่งมักจะมาจาก DB);
  • ภายในวิธีการประมวลผลใส่ข้อมูลจากพื้นที่เก็บข้อมูล (aka ฐานข้อมูลซึ่งส่งคืนข้อมูลที่สั่งซื้อแล้ว) ในคอลเลกชัน LinkedHashMap ที่เฉพาะเจาะจงเพราะนี่คือรายละเอียดภายในของอัลกอริทึมการประมวลผล (เพราะขึ้นอยู่กับวิธีการจัดเรียงข้อมูลในโครงสร้างข้อมูล );
  • โปรดทราบว่านี่เป็นสิ่งที่คุณทำอยู่แล้ว แต่ในกรณีนี้จะทำในวิธีการประมวลผล พื้นที่เก็บข้อมูลของคุณถูกสร้างขึ้นที่อื่น (คุณมีคลาสที่ส่งคืนข้อมูลอยู่แล้วซึ่งเป็นที่เก็บในตัวอย่างนี้)

ตัวอย่างรหัส

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

ฉันเดาว่านี่จะกำจัดคำเตือน Sonar และระบุในเค้าโครงเฉพาะของลายเซ็นของข้อมูลที่ต้องการโดยวิธีการประมวลผล


อืม แต่ที่เก็บจะสร้างอินสแตนซ์ได้อย่างไร นี่จะไม่เป็นการแก้ปัญหาที่อื่น (ไปยังที่ที่MyTupleRepositoryถูกสร้างขึ้น)
Vidar S. Ramdal

ฉันคิดว่าฉันจะใช้เป็นปัญหาเช่นเดียวกับที่มีคำตอบปีเตอร์คูเปอร์
Vidar S. Ramdal

ข้อเสนอแนะของฉันเกี่ยวข้องกับการใช้หลักการฉีดพึ่งพา ในตัวอย่างนี้ MyTupleRepository เป็นอินเทอร์เฟซที่กำหนดความสามารถในการดึง tuples ที่คุณกล่าวถึง (ซึ่งแบบสอบถาม DB) ที่นี่คุณฉีดวัตถุนี้ลงในวิธีการประมวลผล คุณมีคลาสที่ส่งคืนข้อมูลอยู่แล้ว นี่เป็นเพียงนามธรรมในอินเทอร์เฟซและคุณฉีดวัตถุเข้าไปในวิธีการ 'processData' ซึ่งใช้ LinkedHashMap ภายในเนื่องจากนี่เป็นส่วนหนึ่งของการประมวลผล
Emerson Cardoso

ฉันแก้ไขคำตอบพยายามที่จะชัดเจนยิ่งขึ้นเกี่ยวกับสิ่งที่ฉันแนะนำ
Emerson Cardoso

-1

คำถามนี้จริง ๆ แล้วเป็นปัญหาใหญ่ของแบบจำลองข้อมูลของคุณ คุณต้องเริ่มแกะพวกเขาทีละครั้ง โซลูชันที่เป็นธรรมชาติและใช้งานง่ายกว่าจะเลื่อนออกมาในขณะที่คุณพยายามทำให้ปริศนาแต่ละชิ้นง่ายขึ้น

ปัญหาที่ 1: คุณไม่สามารถพึ่งพาคำสั่ง DB ได้

รายละเอียดการเรียงลำดับข้อมูลของคุณไม่ชัดเจน

  • ปัญหาที่ใหญ่ที่สุดที่อาจเกิดขึ้นคือคุณไม่ได้ระบุการเรียงลำดับที่ชัดเจนในฐานข้อมูลของคุณผ่านทางORDER BYประโยค หากคุณไม่ได้เพราะมันดูเหมือนว่าราคาแพงเกินไปโปรแกรมของคุณมีข้อผิดพลาด ฐานข้อมูลได้รับอนุญาตให้ส่งคืนผลลัพธ์ในลำดับใดก็ได้หากคุณไม่ได้ระบุไว้ คุณไม่สามารถพึ่งพาข้อมูลที่ส่งคืนตามลำดับโดยบังเอิญเพียงเพราะคุณเรียกใช้แบบสอบถามสองสามครั้งและดูเหมือนว่าจะเป็นเช่นนั้น ลำดับอาจเปลี่ยนแปลงได้เนื่องจากแถวต่างๆถูกจัดเรียงใหม่บนดิสก์หรือบางส่วนถูกลบและแถวใหม่จะเข้าแทนที่หรือเพิ่มดัชนี คุณต้องระบุORDER BYประโยคบางอย่าง ความเร็วนั้นไร้ค่าโดยไม่มีความถูกต้อง
  • ยังไม่ชัดเจนว่าคุณหมายถึงอะไรโดยลำดับการแทรกสำคัญ หากคุณกำลังพูดถึงฐานข้อมูลเองคุณต้องมีคอลัมน์ที่ติดตามสิ่งนี้จริงและจะต้องรวมอยู่ในORDER BYข้อของคุณ มิฉะนั้นคุณมีข้อบกพร่อง หากยังไม่มีคอลัมน์ดังกล่าวคุณจะต้องเพิ่มอีกหนึ่งคอลัมน์ ตัวเลือกทั่วไปสำหรับคอลัมน์เช่นนี้จะเป็นคอลัมน์เวลาประทับหรือคีย์ที่เพิ่มขึ้นอัตโนมัติ คีย์การเพิ่มโดยอัตโนมัติมีความน่าเชื่อถือมากกว่า

ปัญหาที่ 2: การจัดเรียงหน่วยความจำมีประสิทธิภาพ

เมื่อคุณให้แน่ใจว่ามันรับประกันที่ได้กลับข้อมูลในการสั่งซื้อที่คุณคาดว่าคุณสามารถใช้ประโยชน์จากความเป็นจริงนี้จะทำให้ในหน่วยความจำประเภทมากมีประสิทธิภาพมากขึ้น เพียงเพิ่มrow_number()หรือdense_rank()คอลัมน์ (หรือเทียบเท่าฐานข้อมูลของคุณ) ในชุดผลลัพธ์ของแบบสอบถาม ตอนนี้แต่ละแถวมีดัชนีที่จะให้การบ่งชี้โดยตรงถึงสิ่งที่ควรจะเป็นและคุณสามารถเรียงลำดับสิ่งนี้ในหน่วยความจำได้เล็กน้อย ตรวจสอบให้แน่ใจว่าคุณตั้งชื่อดัชนีที่มีความหมาย (เช่นsortedBySomethingIndex)

ไวโอลินใหญ่ ตอนนี้คุณไม่จำเป็นต้องพึ่งพาคำสั่งชุดผลลัพธ์ของฐานข้อมูลอีกต่อไป

ปัญหาที่ 3: คุณจำเป็นต้องทำการประมวลผลด้วยรหัสหรือไม่

SQL เป็นจริงจริงๆมีประสิทธิภาพมันเป็นภาษาที่มีการประกาศที่ยอดเยี่ยมที่ให้คุณทำการแปลงและรวบรวมข้อมูลของคุณได้มากมาย DBs ส่วนใหญ่รองรับการทำงานข้ามแถวในปัจจุบัน พวกเขากำลังเรียกว่าฟังก์ชั่นหน้าต่างหรือการวิเคราะห์:

คุณจำเป็นต้องดึงข้อมูลของคุณลงในหน่วยความจำเช่นนี้หรือไม่? หรือคุณสามารถทำงานทั้งหมดในแบบสอบถาม SQL โดยใช้ฟังก์ชันหน้าต่างได้หรือไม่ หากคุณสามารถทำทุกอย่าง (หรืออาจเป็นเพียงส่วนสำคัญ) ของงานในฐานข้อมูลน่าอัศจรรย์! ปัญหารหัสของคุณหายไป (หรือง่ายขึ้นมาก)!

ปัญหาที่ 4: คุณกำลังทำสิ่งนั้นอยู่ data ?

สมมติว่าคุณไม่สามารถทำได้ทั้งหมดใน DB ให้ฉันได้สิ่งนี้โดยตรง คุณกำลังใช้ข้อมูลเป็นแผนที่ (ซึ่งเป็นสิ่งสำคัญที่คุณไม่ต้องการเรียงลำดับ) จากนั้นคุณก็ทำการวนซ้ำในตามลำดับการแทรกและปรับเปลี่ยนแผนที่โดยแทนที่ค่าของคีย์และการเพิ่ม อันใหม่?

ฉันขอโทษ แต่สิ่งที่ห่า

สายที่ไม่ควรต้องกังวลเกี่ยวกับทั้งหมดนี้ ระบบที่คุณสร้างนั้นยอดเยี่ยมมากที่เปราะบาง ใช้ความผิดพลาดเพียงครั้งเดียว (อาจทำให้ตัวเองเหมือนที่เราเคยทำ) เพื่อทำการเปลี่ยนแปลงที่ผิดพลาดเพียงเล็กน้อยและทุกอย่างพังทลายลงเหมือนสำรับไพ่

นี่อาจเป็นความคิดที่ดีกว่า:

  • ให้ฟังก์ชั่นของคุณยอมรับ Listมีฟังก์ชั่นของคุณยอมรับ
  • มีสองวิธีที่คุณสามารถจัดการปัญหาการสั่งซื้อได้
    1. สมัครล้มเหลวอย่างรวดเร็ว โยนข้อผิดพลาดหากรายการไม่อยู่ในลำดับที่ฟังก์ชันต้องการ (หมายเหตุ: คุณสามารถใช้ดัชนีการเรียงลำดับจากปัญหา 2 เพื่อบอกได้ว่าเป็นหรือไม่)
    2. สร้างสำเนาที่เรียงลำดับตัวเอง (อีกครั้งโดยใช้ดัชนีจากปัญหา 2)
    3. คิดหาวิธีในการสร้างแผนที่ตามลำดับ
  • สร้างแผนที่ที่คุณต้องการภายในฟังก์ชั่นดังนั้นผู้โทรไม่ต้องสนใจมัน
  • ทวนสิ่งที่คุณมีและทำตามที่คุณต้องการ
  • ส่งคืนแผนที่หรือแปลงเป็นค่าตอบแทนที่เหมาะสม

รูปแบบที่เป็นไปได้อาจสร้างการแสดงแบบเรียงแล้วสร้างแผนที่ของคีย์ไปที่ดัชนีดัชนีสิ่งนี้จะช่วยให้คุณแก้ไขสำเนาที่เรียงลำดับไว้โดยไม่ตั้งใจสร้างสำเนาซ้ำ

หรืออาจเป็นการเหมาะสมกว่า: กำจัดdataพารามิเตอร์และทำให้processDataดึงข้อมูลของตัวเองได้จริง จากนั้นคุณสามารถทำเอกสารว่าคุณทำเช่นนี้เพราะมีข้อกำหนดที่เฉพาะเจาะจงมากเกี่ยวกับวิธีการดึงข้อมูล กล่าวอีกนัยหนึ่งทำให้ฟังก์ชันเป็นเจ้าของกระบวนการทั้งหมดไม่ใช่แค่ส่วนเดียว การพึ่งพาระหว่างกันนั้นแข็งแกร่งเกินกว่าที่จะแยกตรรกะออกเป็นส่วนย่อย ๆ (เปลี่ยนชื่อของฟังก์ชันในกระบวนการ)

บางทีสิ่งเหล่านี้อาจใช้ไม่ได้กับสถานการณ์ของคุณ ฉันไม่รู้โดยไม่มีรายละเอียดของปัญหา แต่ฉันรู้ถึงการออกแบบที่เปราะบางและสับสนเมื่อฉันได้ยิน

สรุป

ฉันคิดว่าปัญหาที่นี่ในท้ายที่สุดแล้วว่าปีศาจอยู่ในรายละเอียด เมื่อฉันเริ่มมีปัญหาเช่นนี้มักเป็นเพราะฉันมีการแสดงข้อมูลที่ไม่เหมาะสมสำหรับปัญหาที่ฉันพยายามแก้ไขจริง ทางออกที่ดีที่สุดคือการหาตัวแทนที่ดีกว่าและจากนั้นปัญหาของฉันกลายเป็นเรื่องง่าย (อาจไม่ใช่เรื่องง่าย แต่ตรงไปตรงมา) เพื่อแก้ไข

หาคนที่ได้รับจุดนั้น: งานของคุณคือลดปัญหาของคุณให้เป็นชุดที่เรียบง่ายตรงไปตรงมา จากนั้นคุณสามารถสร้างรหัสที่แข็งแกร่งและใช้งานง่าย คุยกับพวกเขา. รหัสที่ดีและการออกแบบที่ดีทำให้คุณคิดว่าคนงี่เง่าคนไหนที่คิดพวกเขาเพราะมันเรียบง่ายและตรงไปตรงมา อาจมีนักพัฒนาอาวุโสที่มีความคิดที่คุณสามารถพูดคุยกับ


"คุณหมายถึงว่าไม่มีคำสั่งที่เป็นธรรมชาติ แต่ลำดับการแทรกมีความสำคัญหรือไม่คุณกำลังบอกว่ามันเป็นเรื่องสำคัญที่ข้อมูลจะถูกแทรกลงในตาราง DB แต่คุณไม่มีคอลัมน์ที่สามารถบอกคุณได้ว่าสิ่งที่แทรกอยู่ในลำดับใด - คำถามระบุสิ่งนี้: "การเรียงลำดับแผนที่จะเป็นการดำเนินการที่หนักหน่วงดังนั้นฉันต้องการหลีกเลี่ยงการทำเช่นนั้นเนื่องจากผลลัพธ์แบบสอบถามถูกเรียงลำดับแล้ว" นี้อย่างชัดเจนหมายความว่ามีเป็นคำสั่งที่ชัดเจน calculatable ข้อมูลเพราะมิฉะนั้นการเรียงลำดับมันจะเป็นไปไม่ได้มากกว่าหนัก แต่ว่าคำสั่งที่กำหนดไว้จะแตกต่างกับธรรมชาติของคีย์
จูลส์

2
กล่าวอีกนัยหนึ่ง OP กำลังทำงานกับผลลัพธ์ของแบบสอบถามที่ต้องการselect key, value from table where ... order by othercolumnและจำเป็นต้องรักษาลำดับในการประมวลผล เพื่อแทรกพวกเขากำลังหมายถึงเป็นคำสั่งการแทรกลงในแผนที่ของพวกเขาที่กำหนดไว้ตามคำสั่งที่ใช้ในการค้นหาของพวกเขาไม่ได้เพื่อแทรกลงในฐานข้อมูล สิ่งนี้ชัดเจนโดยใช้LinkedHashMapซึ่งเป็นโครงสร้างข้อมูลที่มีลักษณะทั้งคู่MapและของListคู่คีย์ - ค่า
จูลส์

@Jules ฉันจะทำความสะอาดส่วนนั้นเล็กน้อยขอบคุณ (จริง ๆ แล้วฉันจำได้ว่าอ่าน แต่เมื่อฉันตรวจสอบสิ่งต่าง ๆ ในขณะที่เขียนคำถามฉันไม่สามารถหาได้ฮ่า ๆ มีวัชพืชด้วย) แต่คำถามไม่ชัดเจนว่าพวกเขากำลังทำอะไรกับ DB แบบสอบถามและไม่ว่าพวกเขามีการเรียงลำดับที่ชัดเจนหรือไม่ พวกเขายังกล่าวอีกว่า "ลำดับการแทรกมีความสำคัญ" ประเด็นก็คือแม้ว่าการเรียงลำดับจะหนักคุณไม่สามารถพึ่งพา DB เพื่อสั่งสิ่งต่าง ๆ อย่างถูกต้องได้อย่างน่าอัศจรรย์หากคุณไม่ได้บอกให้ชัดเจน และถ้าคุณจะทำมันใน DB แล้วคุณสามารถใช้ "ดัชนี" เพื่อให้มันมีประสิทธิภาพในรหัส
jpmc26

* เขียนคำตอบ (คิดว่าฉันควรจะเข้านอนเร็ว ๆ นี้)
jpmc26

ใช่ @Jules นั้นถูกต้อง มีเป็นorder byข้อในแบบสอบถาม แต่มันเป็นเรื่องที่ไม่น่ารำคาญ ( ไม่เพียงorder by column) ดังนั้นฉันต้องการที่จะหลีกเลี่ยงการ reimplementing การเรียงลำดับในชวา แม้ว่า SQL จะมีประสิทธิภาพ (และเรากำลังพูดถึงฐานข้อมูล Oracle 11g ที่นี่) ลักษณะของprocessDataอัลกอริทึมทำให้ง่ายต่อการแสดงใน Java และใช่ "ลำดับการแทรก" หมายถึง " ลำดับการแทรกแผนที่ " เช่นลำดับผลลัพธ์แบบสอบถาม
Vidar S. Ramdal
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.