• 0
vector_ever

HashList تخزن عناصر متمائلة ومكررة

سؤال

من المتعارف عليه ان الـ HashList لا تخزن عناصر متكررة على عكس ArrayList  

الآن انا في حيرة من امري حيث انني اثناء محاولتي كتابة كود في برنامج طويل اردت ان استثني العناصر المتكررة فلجات الى HashList لكنني فوجئت انها تخزن تلك العناصر مهما تكررت
ساضرب مثال صغير كتبته اليوم كي اشرح المشكلة

import java.util.Comparator;public class Employee{        private int id;    private String name;    private String address;    private double salary;    public Employee(int id, String name, String address, double salary) {        this.id = id;        this.name = name;        this.address = address;        this.salary = salary;    }    public String getAddress() {        return address;    }    public void setAddress(String address) {        this.address = address;    }    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public double getSalary() {        return salary;    }    public void setSalary(double salary) {        this.salary = salary;    }        public String toString(){        return "ID:" + getId() + ", Name:" + getName() + ", Address:" + getAddress() + ", Salary:" + getSalary();    }            }

الآن ساقوم بعمل عدة كائنات من الكلاس  موظف وتخزين هذه الكائنات مرة في ArrayList  ومرة في HashList

import java.util.ArrayList;import java.util.HashSet;import java.util.Set;public class Main {        public static void main(String args[]) {        Employee ts1 = new Employee (10, "Ali", "Aleppo", 200.0);        Employee ts2 = new Employee (11, "Amal", "Berlin", 600.0);        Employee ts3 = new Employee (12, "Salim", "Homs", 250.0);        Employee ts4 = new Employee (10, "Ali", "Aleppo", 200.0);        Employee ts5 = new Employee (14, "yaser", "Damas", 210.0);               ArrayList<Employee> list = new ArrayList<Employee>();            list.add(ts1);        list.add(ts2);        list.add(ts3);        list.add(ts4);        list.add(ts5);                System.out.println("List");        System.out.println("===================================================");        for (int i = 0; i < list.size(); i++){            System.out.println(list.get(i));        }                Set<Employee> set = new HashSet<Employee>();                set.add(ts1);        set.add(ts2);        set.add(ts3);        set.add(ts4);        set.add(ts5);                System.out.println("");        System.out.println("Set");        System.out.println("===================================================");    for(Employee item: set){         System.out.println(item);    }    }}

عندها افاجأ بأن لا فرق بين النتيجتين سوء الترتيب بحيث أن HashList قامت بتخزين الموظف Ali ذو الرقم 10 مرتين

List===================================================ID:10, Name:Ali, Address:Aleppo, Salary:200.0ID:11, Name:Amal, Address:Berlin, Salary:600.0ID:12, Name:Salim, Address:Homs, Salary:250.0ID:10, Name:Ali, Address:Aleppo, Salary:200.0ID:14, Name:yaser, Address:Damas, Salary:210.0Set===================================================ID:12, Name:Salim, Address:Homs, Salary:250.0ID:10, Name:Ali, Address:Aleppo, Salary:200.0ID:14, Name:yaser, Address:Damas, Salary:210.0ID:10, Name:Ali, Address:Aleppo, Salary:200.0ID:11, Name:Amal, Address:Berlin, Salary:600.0

ربما لانه الكائن يحوي عناصر متعددة فلذلك عجز الهاش ليست على المقارنة
ما الحل يا اخوة؟

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

4 إجابة على هذا السؤال .

  • 0

الHash Table بشكل عام تحتاج الدالة hashCode  والدالة equals في الكلاس، انت الان تستخدم الدالة الموجودة في الكلاس Object ولكنها ترجع قيم مختلفة للموظف الأول والرابع لذلك هم مختلفين، يجب ان تعيد تعريفها.

 

ضع الدالتين التاليتين وهم في ابسط شكل بسبب انك تقارن بال id:

 

@Overridepublic boolean equals(Object otherObject) {if ( otherObject == this )return true;if ( otherObject == null || !(otherObject instanceof Employee))return false;Employee other = (Employee) otherObject;return other.id == this.id;}@Overridepublic int hashCode() {return  id;}

هناك قواعد وشروط لكتابه دالة equals وال hashcode يجب مراعتها،،

 

نظرة حول الدالة Equals
 
بالتوفيق،
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

نعم أخي وجدي انا البارحة وصلت لحل هذه المشكلة وقمت باضافة ما يلي:

 @Override   public boolean equals(Object obj){           if(!(obj instanceof Employee))              return false;           return (id == ((Employee) obj).getId());       }        @Override    public int hashCode(){           return  id;        }

الآن واضح انه يعمل بشكل تمام كما في ردك لكنني أريد الاستزادة والاستفاضة بالموضوع لانني طرحت هذا الكود وهو ليس غايتي بقدر ما غايتي معرفة سلوك Set  وآلية عملها وما اتمناه ان احصل منك على المساعدة

 

الأن واضح انه يقارن بين القيم id فاذا كانت متطابقة فيجب عدم اضافتها للـ HashSet  الآن لو أردت تطوير المثال والقول انه اذا كان مثلا اما الـ id  أو الـ name متكررين فيجب عدم اضافتهم للـ HashSet  

حاولت عمل ذلك كما يلي:

    @Override   public boolean equals(Object obj1){           if(!(obj1 instanceof Employee))              return false;           return (id == ((Employee) obj1).getId() || name.equals(((Employee) obj1).getName()));       }        @Override    public int hashCode(){           return  id ^ name.hashCode();        }

لكنني لم احصل على مبتغاي فكيف يجب كتابة الكود بشكل كامل وصحيح ليحقق لي هدفي

 

هذه نقطة اما النقطة الثانية فهي ماذا لو اسنخدمت الـ TreeSet عندها ما هي الـ methods  التي ساستخدمها بدل  equals والـ hashcode وآلية استخدامهم؟

 

ولك كل المحبة والتقدير والشكر

تم تعديل بواسطه vector_ever
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

مقالك اخي عن دالة Equals مثير للاهتمام ومهم وان كان ليس بالسهل لكنه مبسط وهذا جهد تشكر عليه

مرة اخرى اتمنى ان تقدر على مساعدتي في مشروعي حيث ان طلبي النهائي والهام هو ما كان يعترضني في محاولة قراءة البيانات من ملف اكسل عن طريق مكتبة Apache Poi وتخزين هذه البيانات في ArrayList ثم القيام بتصدير هذه الـ ArrayList الى قاعدة البيانات

 

الآن لسبب ما أرغب بالقيام بقراءة البيانات من ملف الاكسل وتخزينها في قواعد البيانات دون وجود اي تكرار اي عدم وجود أسطر كل قيمها متشابهة (أو بعضها حسب ما نقوم بتحديد ذلك)

لذلك وجدت ان الطريقة الاسلم لذلك هي استخدام Set  حيث ان الـ Set  لا تقوم بتخزين عناصر متمائلة وكنت ارغب باستخدام الـ TreeSet  للمحافظة على ترتيب العناصر (وان كان الـ HashSet تؤدي ما ارغب به ومن الممكن انها أسهل بالتعامل واعادة التعريف من الـ TreeSet  )

على كل بغض النظر ان كنا سنتستخدم الـ TreeSet  او الـ HashSet فان فكرتي كانت انه بداية اقوم بقراءة كل خلية من ملف الاكسل ثم كل سطر وتخزينها في ArrayList وقطعا سوف تحتوي عناصر متكررة ثم اقوم بتحويل الـ ArrayList الى  TreeSet  او HashSet وبذلك يتم حذف كل العناصر المتكررة

import java.io.File;import java.io.FileInputStream;import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.util.ArrayList;import java.util.HashSet;import java.util.Iterator;import java.util.Set;import java.util.TreeSet;import org.apache.poi.hssf.usermodel.HSSFCell;import org.apache.poi.hssf.usermodel.HSSFSheet;import org.apache.poi.hssf.usermodel.HSSFWorkbook;import org.apache.poi.ss.usermodel.Cell;import org.apache.poi.ss.usermodel.Row;public class Tst {	//static ArrayList cellArrayLisstHolder = new ArrayList();		public static void main(String[] args) throws Exception{				ArrayList dataHolder = readExcelFile(); 		//saveToDatabase(dataHolder);				System.out.println("With List");		for (int i = 0; i < dataHolder.size(); i++){			System.out.println(dataHolder.get(i));		}				System.out.println("--------------------------------------------------------------------------");		System.out.println("--------------------------------------------------------------------------");				Set set = new HashSet(dataHolder);		System.out.println("With Set");		ArrayList noDuplicate  = new ArrayList(set);		for (int i = 0; i < noDuplicate.size(); i++){			System.out.println(noDuplicate.get(i));		}	}				public static ArrayList readExcelFile(){					ArrayList dataSheet = new ArrayList();			try {	     	    FileInputStream file = new FileInputStream(new File("d:\\Songs.xls"));	     	    //Get the workbook instance for XLS file 	    HSSFWorkbook workbook = new HSSFWorkbook(file);	 	    //Get first sheet from the workbook	    HSSFSheet sheet = workbook.getSheetAt(0);	     	    //Iterate through each rows from first sheet	    Iterator<Row> rowIterator = sheet.iterator();	    while(rowIterator.hasNext()) {	        Row row = rowIterator.next();	        	        //display from the first row 	        if(row.getRowNum() > 0)	        {	       	        //For each row, iterate through each columns	        Iterator<Cell> cellIterator = row.cellIterator();	        	        ArrayList data = new ArrayList();	        	        while(cellIterator.hasNext()) {	            	            //Getting the cell contents	            Cell cell = cellIterator.next();	            	        data.add(cell);	          }	        dataSheet.add(data);		      	        }	        }		    }catch (Exception e){e.printStackTrace(); 		    }		    return dataSheet;		    }}

الآن كما ترى يا صديقي فان الناتج يكون غير ما أريده

With List[4711.0, Not That Kind, Anastacia, 1999.0, 1.0, Not That Kind][4710.0, Not That Kind, Anastacia, 1999.0, 2.0, I’m Outta Love][4713.0, Not That Kind, Anastacia, 1999.0, 3.0, Cowboys & Kisses][4722.0, Wish You  Her, Pink Floyd, 1964.0, 1.0, Shine On You Crazy Diamond][4713.0, Not That Kind, Anastacia, 1999.0, 3.0, Cowboys & Kisses][4711.0, Not That Kind, Anastacia, 1999.0, 1.0, Not That Kind][4712.0, Love you  too, Sps.Girls, 998.0, 1.0, Viva for ever][4710.0, Not That Kind, Anastacia, 1999.0, 2.0, I’m Outta Love][4722.0, Wish You  Her, Pink Floyd, 1964.0, 1.0, Shine On You Crazy Diamond]----------------------------------------------------------------------------------------------------------------------------------------------------With Set[4722.0, Wish You  Her, Pink Floyd, 1964.0, 1.0, Shine On You Crazy Diamond][4711.0, Not That Kind, Anastacia, 1999.0, 1.0, Not That Kind][4710.0, Not That Kind, Anastacia, 1999.0, 2.0, I’m Outta Love][4713.0, Not That Kind, Anastacia, 1999.0, 3.0, Cowboys & Kisses][4713.0, Not That Kind, Anastacia, 1999.0, 3.0, Cowboys & Kisses][4711.0, Not That Kind, Anastacia, 1999.0, 1.0, Not That Kind][4712.0, Love you  too, Sps.Girls, 998.0, 1.0, Viva for ever][4710.0, Not That Kind, Anastacia, 1999.0, 2.0, I’m Outta Love][4722.0, Wish You  Her, Pink Floyd, 1964.0, 1.0, Shine On You Crazy Diamond]

الفكرة بالطبع هو اعادة تعريف دالة الـ Equal  والـ HashSet كما يلي:

@Override   public boolean equals(Object obj){            if(!(obj instanceof myClass))              return false;            return (attribute== ((myClass) obj1).getAttribute());       }          @Override    public int hashCode(){            return  attribute.hashCode();        }

مشكلتي هنا أنني لا اتعامل مع كلاس جاهز قمت انا ببنائه واعرف عناصره ومحتوياته كماهو في الكلاس Employee الذي قمت بتعريف الرقم والاسم والعنوان والراتب

أما هنا فالامر مختلف لا اعرف ماذا سأضع داخل هذه الدوال مثلا obj instanceof myClass ما هو الـ myClass  الذي سأكتبه هنا هل هو Row ام Cell  أم غيرهما ونفس القضية بالنسبة لـ attribute وبالذات انه لا يوجد لدي  setter and getter

 

 

هذه المشكلة تؤرقني منذ 3 ايام ومشروعي متوقف على حلها  فهل من مساعدة في هذه النقطة

 

Songs.xls

poi-3.9.jar

تم تعديل بواسطه vector_ever
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

من خلال مناقشات مستمرة عن طريق الانترنت استخلصت انه لقراءة ملف الاكسل الذي يحتوي على البيانات الخاصة بالـ Employee فيجب انشاء كائن جديد من هذا الصنف داخل الحلقة التي تقوم بقراءة ملف الاكسل سطر سطر وهنا أقصد 

 while(rowIterator.hasNext()) {

ومن ثم تضمين البيانات الخاصة بالكائن employee  وتضمينها في الـ cell  اثناء المرور على كل خلية في السطر

//Iterate through each rows from first sheetIterator<Row> rowIterator = sheet.iterator();while(rowIterator.hasNext()) {    Row row = rowIterator.next();         //display from the first row     if(row.getRowNum() > 0)    {     //For each row, iterate through each columns    Iterator<Cell> cellIterator = row.cellIterator();     Employee employee = new Employee (id, address, address, salary);     Set data = new HashSet();     // missing point about using employee              data.add(employee );      }     }

صراحة هذه العملية لا ادري كيف ساقوم بها ولا يوجد لدي تصور كافي عن كيفية القيام بذلك فاتمنى المساعدة

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

من فضلك سجل دخول لتتمكن من التعليق

ستتمكن من اضافه تعليقات بعد التسجيل



سجل دخولك الان

  • يستعرض القسم حالياً   0 members

    لا يوجد أعضاء مسجلين يشاهدون هذه الصفحة .