سؤال
في الوقت الحاضر ، تكون تكنولوجيا الإنترنت ناضجة ، وأكثر فأكثر تميل إلى أن تكون لا مركزية وتوزيعها ودفق الحوسبة ، والتي وضعت العديد من الأشياء التي تم القيام بها على جانب قاعدة البيانات في جانب Java. سأل أحدهم اليوم ، عما إذا كان حقل قاعدة البيانات لا يحتوي على فهرس ، كيف ينبغي تكريسه بناءً على الحقل؟ يوافق الجميع على استخدام Java للقيام بذلك ، ولكن كيفية القيام بذلك؟
إجابة
فجأة تذكرت المقال الذي كتبته في القائمة لإزالة الأوزان الثقيلة من قبل ، ووجدته وقراءته. تتمثل الطريقة في إعادة كتابة علامات التجزئة ومساواة طرق الكائن في القائمة ، ورميها في Hashset ، ثم أخرجها. هذا هو الإجابة التي كتبتها مثل قاموس عندما تعلمت جافا لأول مرة. على سبيل المثال ، عند إجراء المقابلات ، الأشخاص الذين كانوا في Java لمدة 3 سنوات ، يمكنهم حفظ الفرق بين Set و HashMap ، لكنهم لا يعرفون كيفية تنفيذها. بمعنى آخر ، يحفظ المبتدئون فقط الخصائص. ولكن عندما تستخدمه فعليًا في المشروع ، تحتاج إلى التأكد من أنه صحيح. لأن التأييد عديم الفائدة ، لا أستطيع إلا أن أؤمن بالنتيجة. تحتاج إلى معرفة كيف تساعدني Hashset على إزالة الوزن الثقيل. إذا كنت تفكر في ذلك ، هل يمكنك إزالة الحمل الثقيل بدون Hashset؟ إن أبسط الطرق المباشرة هي مقارنتها بالبيانات التاريخية في كل مرة ، وإدخالها في ذيل قائمة الانتظار إذا كان مختلفًا. و Hashset فقط يسرع هذه العملية.
أولاً ، أعط مستخدم الكائن لفرز
@data@builder@allargsconstructorpublic user {private integer id ؛ اسم السلسلة الخاصة ؛} قائمة <Sether> users = lists.newarrayList (مستخدم جديد (1 ، "A") ، مستخدم جديد (1 ، "B") ، مستخدم جديد (2 ، "B") ، مستخدم جديد (1 ، "A")) ؛الهدف هو إخراج المستخدم بدون معرف مكرر. من أجل منع الشجار ، أعطي قاعدة. ما عليك سوى إخراج البيانات ذات المعرفات الفريدة في الإرادة ، ولا يجب أن تكون ضميرًا حول أي شخص يتم حسابه عندما يكون المعرف هو نفسه.
استخدم الطريقة الأكثر سهولة
هذه الطريقة هي استخدام قائمة فارغة لتخزين البيانات التي تم اجتيازها.
testpublic void dis1 () {list <ser> result = new LinkedList <> () ؛ لـ (مستخدم المستخدم: المستخدمين) {boolean b = result.stream (). anymatch (u -> u.GetId (). equals (user.getId ()))) ؛ if (! b) {result.add (user) ؛ }} system.out.println (result) ؛}استخدم hashset
أي شخص قام بحفظ الميزات يعرف أن Hashset يمكنه إزالة الأوزان الثقيلة ، فكيف يمكنني إزالة الأوزان الثقيلة؟ حفظها أعمق قليلاً ووفقًا لأساليب الهاش ومساواة. فكيف تفعل ذلك بناءً على هذين؟ لا يمكن للأشخاص الذين لم يقرؤوا الكود المصدري الاستمرار ، وتنتهي المقابلة هنا.
في الواقع ، يتم تنفيذ Hashset بواسطة HashMap (لم أر قط الرمز المصدري ، وقد اعتقدت دائمًا أن مفتاح HashMap يتم تنفيذه بواسطة Hashset ، وهو عكس ذلك تمامًا). لن أقوم بتوسيع الوصف هنا ، فقط انظر إلى طريقة البناء وأضف طريقة Hashset لفهمها.
Hashset/public hashset () {map = new hashmap <> () ؛}/*** من الواضح ، إذا كان موجودًا ، فإنه يعيد خطأ ، إذا لم يكن موجودًا ، فإنه يعيد*/boolean public add (e e) {return map.put (e ، present) == null ؛}بعد ذلك ، يمكن ملاحظة ذلك أيضًا أن تكرار hashset يتم تنفيذه بناءً على hashmap ، وأن تنفيذ hashmap يعتمد تمامًا على الأساليب hashcode والطرق المتساوية. الآن تم فتحه بالكامل. إذا كنت ترغب في استخدام Hassset ، فيجب أن تكون متفائلاً بشأن طريقتك.
في هذا السؤال ، نحتاج إلى تعديله بناءً على المعرف ، وبالتالي فإن أساس المقارنة لدينا هو المعرف. التعديلات كما يلي:
Overridepublic Boolean يساوي (كائن O) {if (this == o) {return true ؛ } if (o == null || getClass ()! = o.getClass ()) {return false ؛ } مستخدم المستخدم = (المستخدم) o ؛ إرجاع Objects.equals (id ، user.id) ؛}@outridepublic int hashcode () {return objects.hash (id) ؛} // hashcoderesult = 31 * result + (element == null؟ 0: element.hashcode ()) ؛من بينها ، HOUBSS Calls Arrays 'Hashcode ، والمحتوى كما هو موضح أعلاه. مضاعفة على 31 يساوي x << 5-x.
التنفيذ النهائي هو كما يلي:
testpublic void dis2 () {set <Sether> result = new hashset <> (المستخدمين) ؛ system.out.println (نتيجة) ؛}استخدم Stream Java to Deciduplicate
بالعودة إلى السؤال الأولي ، السبب في طرح هذا السؤال هو أنه إذا كنت ترغب في إعادة تعيين جانب قاعدة البيانات إلى جانب Java ، فقد تكون كمية البيانات كبيرة نسبيًا ، مثل 100000 قطعة. بالنسبة للبيانات الضخمة ، فإن استخدام الوظائف المتعلقة بالدفق هو الأسهل. مثلما يوفر الدفق أيضًا الوظيفة المميزة. فكيف يجب استخدامه؟
users.parallelstream (). DISTER (). foreach (system.out :: println) ؛
لم أر Lambda كمعلمة ، أي أنه لم يتم تقديم شروط مخصصة. لحسن الحظ ، تميزت Javadoc بمعايير الإعلام:
إرجاع دفق يتكون من العناصر المتميزة (وفقًا لـ {link Object#equals (Object)}) من هذا الدفق.نحن نعلم أنه يجب علينا أيضًا حفظ هذا المبدأ: عندما تعيد العوائد بشكل صحيح ، يجب أن تكون قيمة إرجاع رمز Hashcode هي نفسها. هذا مربك بعض الشيء عند الحفظ ، ولكن طالما أننا نفهم طريقة التنفيذ في HashMap ، فلن نشعر صعوبة في التحدث. يحدد موقع HashMap أولاً وفقًا لطريقة HashCode ، ثم يقارن طريقة Equals.
لذلك ، لاستخدام متميز لتحقيق إلغاء البيانات المكررة ، يجب عليك تجاوز الأساليب ومساواة الأساليب إلا إذا كنت تستخدم الطريقة الافتراضية.
فلماذا تفعل هذا؟ انقر في وإلقاء نظرة على التنفيذ.
<p_in> العقدة <T> تقليل (pipelineHelper <T> المساعد ، spliterator <p_in> spitrator) {// إذا تم فرز الدفق ، فيجب أيضًا طلبه ، لذا فإن ما يلي // يحتفظ أيضًا بترتيب الفرز <T ، linkedhash <T> LinkedHashset :: Add ، LinkedHashset :: addall) ؛ العقد الإرجاع. node (lordop.evalperparalald (المساعد ، splitterator)) ؛}يتحقق التنفيذ الداخلي عن طريق الحد. عندما تفكر في التقليل ، تفكر على الفور في طريقة لتنفيذ DistarByKey بنفسك. أنا فقط بحاجة إلى استخدام تقليل ، وجزء الحساب هو مقارنة عناصر الدفق مع hashmap المدمج ، وتخطيها إذا كان هناك ، ووضعها إذا لم يكن هناك. في الواقع ، فإن الفكرة هي الطريقة الأكثر وضوحا في البداية.
testpublic void dis3 () {user.parallelstream (). filter (distarbyKey (user :: getId)). إرجاع t -> see.add (keyextractor.apply (t)) ؛}بالطبع ، إذا كان دفقًا متوازيًا ، فهو الذي يتم أخذه ليس بالضرورة هو الأول ، ولكنه عشوائي.
الطريقة أعلاه هي الأفضل وغير الغازية. ولكن إذا كان عليك استخدام متميز. يمكنك فقط إعادة كتابة Hashcode ومساواة مثل طريقة hashset.
ملخص
يمكنك فقط التدريب على ما إذا كان يمكنك استخدام هذه الأشياء بنفسك. خلاف ذلك ، سيكون من الصعب إخراجهم مرة واحدة عندما تريد حقًا استخدامها ، أو ستحمل المخاطر. وإذا كنت ترغب حقًا في استخدامه بجرأة ، فمن الضروري أيضًا فهم القواعد ومبادئ التنفيذ. على سبيل المثال ، كيف تختلف تطبيقات LinkedHashset و Hashset؟
متصل برمز مصدر LinkedHashset البسيط:
الطبقة العامة LinkedHashset <e> يمتد Hashset <e> الأدوات المُعين <e> ، clonable ، java.io.serializable {private static final long serialversionuid = -2851667679971038690l ؛ sinkedhashset العامة (int initialcapacity ، float loadFactor) {super (initialCapacity ، loadfactor ، true) ؛ } public LinkedHashSet (int initialCapacity) {super (initialCapacity ، .75f ، true) ؛ } public LinkedHashSet () {super (16 ، .75f ، true) ؛ } public LinkedHashset (مجموعة <؟ تمتد e> c) {super (math.max (2*c.size () ، 11) ، .75f ، true) ؛ addall (ج) ؛ } Override public spliterator <e> spliterator () {return splitrators.spliterator (this ، spliterator.distinct | spliterator.ordered) ؛ }}التجديد:
طريقة لإزالة البيانات المكررة من مجموعة القائمة في Java
1. حلقة جميع العناصر في القائمة ثم حذف التكرارات
القائمة الثابتة العامة إزالة (قائمة قائمة) {for (int i = 0 ؛ i <list.size () - 1 ؛ i ++) {for (int j = list. }}} قائمة الإرجاع ؛ } 2. انطلق عناصر مكررة من خلال hashset
القائمة الثابتة العامة إزالة (قائمة قائمة) {hashset h = new hashset (list) ؛ list.clear () ؛ list.addall (h) ؛ قائمة العودة }3. حذف العناصر المكررة في ArrayList للحفاظ على الطلب
// حذف العناصر المكررة في ArrayList ، حافظ على طلب الفراغ الثابت العام readeduplicatewithorder (قائمة) {set set = new hashset () ؛ قائمة newList = new ArrayList () ؛ لـ (iterator iter = list.iterator () ؛ iter.hasnext () ؛) {element element = iter.next () ؛ if (set.add (element)) newList.add (element) ؛ } list.clear () ؛ list.addall (NewList) ؛ System.out.println ("إزالة مكرر" + قائمة) ؛ }4. التكرار على الكائن في القائمة ، واستخدم list.contain () ، وإذا لم يكن موجودًا ، فضعه في مجموعة قائمة أخرى.
القائمة الثابتة العامة إزالة (قائمة قائمة) {list listtemp = new ArrayList () ؛ لـ (int i = 0 ؛ i <list.size () ؛ i ++) {if (! listtemp.contains (list.get (i))) {listtemp.add (list.get (i)) ؛ }} return listtemp ؛ }