يمكن أن تحتوي القائمة في Java على عناصر متكررة (رمز التجزئة والمساواة)، لذلك هناك طريقتان لإلغاء تكرار القائمة:
الخيار 1: يمكن تنفيذه من خلال HashSet، الكود كما يلي:
انسخ رمز الكود كما يلي:
طالب الصف {
معرف السلسلة الخاصة؛
اسم سلسلة خاصة؛
الطالب العام (معرف السلسلة، اسم السلسلة) {
ممتاز()؛
this.id = id;
this.name = name;
}
@تجاوز
سلسلة عامة إلى سلسلة () {
إرجاع "الطالب [معرف = " + معرف + "، اسم = " + اسم + "]"؛
}
@تجاوز
كود التجزئة العام () {
العدد النهائي النهائي = 31؛
نتيجة كثافة العمليات = 1؛
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
نتيجة الإرجاع؛
}
@تجاوز
منطقية عامة يساوي (كائن كائن) {
إذا (هذا == الكائن) {
عودة صحيحة؛
}
إذا (obj == فارغة) {
عودة كاذبة.
}
إذا (getClass() != obj.getClass()) {
عودة كاذبة.
}
Studentother = (Student) obj;
إذا (المعرف == فارغ) {
إذا (other.id != فارغة) {
عودة كاذبة.
}
} وإلا إذا (!id.equals(other.id)) {
عودة كاذبة.
}
إذا (الاسم == فارغ) {
إذا (اسم آخر! = فارغ) {
عودة كاذبة.
}
} وإلا إذا (!name.equals(other.name)) {
عودة كاذبة.
}
عودة صحيحة؛
}
}
يجب تنفيذ طريقتين، hashCode وequals، وسنرى بعد قليل لماذا يجب تنفيذ أكواد التشغيل المحددة على النحو التالي:
انسخ رمز الكود كما يلي:
إزالة الفراغ الثابت الخاص () {
List<Student> list = new ArrayList<Student>();
لـ (int i = 0; i < 10; i++) {
Student Student = new Student("id", "name");
list.add(student);
}
System.out.println(Arrays.toString(list.toArray()));
Set<Student> set = new HashSet<Student>();
set.addAll(list);
System.out.println(Arrays.toString(set.toArray()));
list.removeAll(list);
set.removeAll(set);
System.out.println(Arrays.toString(list.toArray()));
System.out.println(Arrays.toString(set.toArray()));
}
رمز الاتصال:
انسخ رمز الكود كما يلي:
public static void main(String[] args) {
RemoveListDuplicateObject();
}
عند استخدام HashSet لإجراء عمليات إلغاء البيانات المكررة، لماذا نحتاج إلى تجاوز طريقتي hashCode وequals؟
دعونا نتحقق من الكود المصدري لعملية الإضافة الخاصة بـ HashSet كما يلي:
انسخ رمز الكود كما يلي:
إضافة منطقية عامة (E e) {
إرجاع Map.put(e, PRESENT)==null;
}
تم استدعاء HashMap للتشغيل، فلنلقِ نظرة على عملية وضع HashMap:
انسخ رمز الكود كما يلي:
وضع V العام (مفتاح K، قيمة V) {
إذا (مفتاح == فارغ)
إرجاع putForNullKey(value);
int hash = hash(key.hashCode());
int i = IndexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
كائن ك؛
إذا (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
القيمة الإلكترونية = القيمة؛
e.recordAccess(this);
إرجاع القيمة القديمة؛
}
}
modCount++;
addEntry(hash, key, value, i);
عودة فارغة؛
}
الأشياء التي يجب ملاحظتها هي:
انسخ رمز الكود كما يلي:
إذا (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
...
}
بمعنى آخر، رموز التجزئة متساوية وتساوي (==).
التعقيد: مجرد اجتياز جانب واحد، O(n)
الخيار 2: اجتياز القائمة مباشرةً وتنفيذ عمليات الاحتواء والإضافة، ويكون الكود كما يلي:
انسخ رمز الكود كما يلي:
إزالة الفراغ الثابت الخاص RemoveListDuplicateObjectByList() {
List<Student> list = new ArrayList<Student>();
لـ (int i = 0; i < 10; i++) {
Student Student = new Student("id", "name");
list.add(student);
}
System.out.println(Arrays.toString(list.toArray()));
List<Student> listUniq = new ArrayList<Student>();
لـ (الطالب الطالب: القائمة) {
إذا (!listUniq.contains(student)) {
listUniq.add(student);
}
}
System.out.println(Arrays.toString(listUniq.toArray()));
list.removeAll(list);
listUniq.removeAll(listUniq);
System.out.println(Arrays.toString(list.toArray()));
System.out.println(Arrays.toString(listUniq.toArray()));
}
البعض الآخر هو نفسه على النحو الوارد أعلاه.
تعقيد:
أثناء العبور، يتم استدعاء الأسلوب يحتوي في نفس الوقت، ونعرض الكود المصدري على النحو التالي:
انسخ رمز الكود كما يلي:
منطقية عامة تحتوي على (كائن س) {
مؤشر الإرجاع (س) >= 0;
}
مؤشر كثافة العمليات العام (كائن س) {
إذا (س == فارغة) {
لـ (int i = 0; i < size; i++)
إذا (elementData[i]==null)
العودة أنا؛
} آخر {
لـ (int i = 0; i < size; i++)
إذا (o.equals(elementData[i]))
العودة أنا؛
}
العودة -1؛
}
يمكنك أن ترى أنه قد تم تنفيذ عملية اجتياز أخرى في القائمة الجديدة. أي 1+2+....+n، التعقيد هو O(n*n)
ختاماً:
الحل 1 فعال للغاية، أي استخدام HashSet لإجراء عمليات إلغاء البيانات المكررة.