الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

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

بدأه vector_ever في 2 أغسطس 2013 · 4 رد · 964 مشاهدة · في JavaSE
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

من المتعارف عليه ان الـ 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.0
ID:11, Name:Amal, Address:Berlin, Salary:600.0
ID:12, Name:Salim, Address:Homs, Salary:250.0
ID:10, Name:Ali, Address:Aleppo, Salary:200.0
ID:14, Name:yaser, Address:Damas, Salary:210.0

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

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

إذا نظــرتَ نيـوب اللـّيـثِ بـارزةً         فـلا تظــنَنَ أَنَّ اللـّيـــثَ يبْتسـِـــمُ


 


 


رسم المخططات البيانية بواسطة الجافا


 


كتاب تحليل وتصميم نظم المعلومات


#2

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

 

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

 

@Override
public 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;
}


@Override
public int hashCode() {
return  id;
}

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

 

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

http://informatic-ar.com منصة تعليمية عربية في علوم الحاسب والبرمجة

https://moalfat.com  للكتب الالكترونية والكورسات التعليمية

Everything we see now is just an engineering solution based on old science

#3

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

 @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 في 3 أغسطس 2013 في 16:35

إذا نظــرتَ نيـوب اللـّيـثِ بـارزةً         فـلا تظــنَنَ أَنَّ اللـّيـــثَ يبْتسـِـــمُ


 


 


رسم المخططات البيانية بواسطة الجافا


 


كتاب تحليل وتصميم نظم المعلومات


#4

مقالك اخي عن دالة 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 في 3 أغسطس 2013 في 20:03

إذا نظــرتَ نيـوب اللـّيـثِ بـارزةً         فـلا تظــنَنَ أَنَّ اللـّيـــثَ يبْتسـِـــمُ


 


 


رسم المخططات البيانية بواسطة الجافا


 


كتاب تحليل وتصميم نظم المعلومات


#5

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

 while(rowIterator.hasNext()) {

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

//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();
 
    Employee employee = new Employee (id, address, address, salary);
 
    Set data = new HashSet();
 
    // missing point about using employee 
         
    data.add(employee );
      }
 
    }

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

إذا نظــرتَ نيـوب اللـّيـثِ بـارزةً         فـلا تظــنَنَ أَنَّ اللـّيـــثَ يبْتسـِـــمُ


 


 


رسم المخططات البيانية بواسطة الجافا


 


كتاب تحليل وتصميم نظم المعلومات


مواضيع مشابهة

عدد الزوار حالياً

المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية

—الإجمالي—أعضاء مسجّلون—زوار بدون تسجيل

جارٍ التحقق من المتواجدين…