1. 程式人生 > >一道Java集合框架題

一道Java集合框架題

         問題:某班30個學生的學號為20070301-20070330,全部選修了Java程式設計課程,給出所有同學的成績(可用隨機數產生,範圍60-100),請編寫程式將本班各位同學的成績按照從低到高排序列印輸出。

     要求:分別用List、Map、Set來實現,列印的資訊包括學號、姓名和成績。

1、使用List集合來實現

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.TreeMap;



public class Test2{
	
	public static void main(String[] args){
		
		/* 此處用ArrayList實現
		 * 
		 * ArrayList<Student>al=new ArrayList<Student>();
		for(int i=20070301,j=10;i<=20070330;i++,j++)
	    {
	        al.add(new Student(i,(int) (40*Math.random()+60), "同學"+j));
	    }
		
		//ArrayList排序藉助Collections中的sort()方法實現。
		Collections.sort(al, new Sortbygrade());
		for(Student sd:al)
		System.out.println(sd);
		
		*/
		
		LinkedList<Student> lt=new LinkedList<Student>();
		for(int i=20070301,j=10;i<=20070330;i++,j++)
	    {
	        lt.add(new Student(i,(int) (40*Math.random()+60), "同學"+j));
	    }
		
		//對連結串列排序
		Collections.sort(lt, new Sortbygrade());
		//輸出連結串列
		for(Student sd:lt)
			System.out.println(sd);
		
	}
	
}



//學生類
class Student{
	int num,grade;
	String name;
	
	//建構函式
	public Student(int num,int grade,String name){
		
		this.num=num;
		this.name=name;
		this.grade=grade;
	}
	
	//此處必須覆寫
	public String toString(){
//		System.out.println("hi");
		return "學號:"+this.num+"\t"+"姓名:"+this.name+"    "+"成績:"+this.grade;
	}
	
}

//建立一個比較器類
class Sortbygrade implements Comparator<Student>{

	@Override
	public int compare(Student s1, Student s2) {
		
		if(s1.grade>s2.grade)
			return 1;
		if(s1.grade<s2.grade)
			return -1;
		if(s1.grade==s2.grade)
			return s1.name.compareTo(s2.name);
		return 0;		
		
	}
	
}
輸出結果如圖:



對List集合框架的總結:

1、List集合其實是一個動態的陣列,元素可以直接通過for迴圈取出,而不需要迭代。

2、輸出List集合時,會預設呼叫集合中儲存物件的toString()方法,所以在類中需要進行覆寫。

若不覆寫toString( )方法,則必須使用

for(int i=0;i<lt.size();i++)
{
	Student s=lt.get(i);
	System.out.println("學號:"+s.num+"    姓名:"+s.name+"    成績:"+s.grade);
}

3、List集合的排序需要藉助於Collections工具類,即Collections.Sort(list,new 比較器類())

方法。所以需要自定義一個比較器類,定義自己的比較規則。

2、使用Set集合來實現

(1)使用TreeSet來實現

package com.package1;

import java.util.*;

public class StuScore {

public static void main(String[] args) {

    TreeSet<Student> ts=new TreeSet<Student>(new Com());
    //新增元素進去
    for(int i=20070301,j=1;i<=20070330;i++,j++)
    {
        ts.add(new Student(i,"同學"+j,(int) (40*Math.random()+60)));
    }

    //迭代迴圈取出
    Iterator<Student> it=ts.iterator();
    while(it.hasNext())
    {
        Student o1=it.next();
        System.out.println("學號:"+o1.num+"  "+"姓名:"+o1.name+"  "+"  "+"成績:"+o1.grade);

    }

}
}
//學生類
class Student 
{
int num;
int grade;
String name;


public Student(int num, String name,int grade)
{
    this.num=num;
    this.name=name;
    this.grade=grade;
}
}
class Com implements Comparator
{

@Override
public int compare(Object o1, Object o2) {

    Student s1=(Student) o1;
    Student s2=(Student) o2;
    if(s1.grade>s2.grade)
        return 1;
    if(s1.grade<s2.grade)
        return -1;
    if(s1.grade==s2.grade)
    {
        return new Integer(s1.num).compareTo(new Integer(s2.num));
    }
    return 0;
}
}

輸出結果為:

學號:20070307  姓名:同學16    成績:60
學號:20070309  姓名:同學18    成績:60
學號:20070314  姓名:同學23    成績:61
學號:20070318  姓名:同學27    成績:61
學號:20070322  姓名:同學31    成績:61
學號:20070306  姓名:同學15    成績:62
學號:20070310  姓名:同學19    成績:64
學號:20070302  姓名:同學11    成績:66
學號:20070308  姓名:同學17    成績:68
學號:20070321  姓名:同學30    成績:68
學號:20070330  姓名:同學39    成績:69
學號:20070303  姓名:同學12    成績:70
學號:20070320  姓名:同學29    成績:70
學號:20070323  姓名:同學32    成績:77
學號:20070313  姓名:同學22    成績:78
學號:20070304  姓名:同學13    成績:79
學號:20070324  姓名:同學33    成績:83
學號:20070326  姓名:同學35    成績:84
學號:20070327  姓名:同學36    成績:85
學號:20070311  姓名:同學20    成績:88
學號:20070305  姓名:同學14    成績:89
學號:20070329  姓名:同學38    成績:89
學號:20070316  姓名:同學25    成績:90
學號:20070301  姓名:同學10    成績:95
學號:20070312  姓名:同學21    成績:96
學號:20070317  姓名:同學26    成績:97
學號:20070319  姓名:同學28    成績:97
學號:20070325  姓名:同學34    成績:98
學號:20070315  姓名:同學24    成績:99
學號:20070328  姓名:同學37    成績:99

對TreeSet的總結:

1、元素不可以重複,而且TreeSet是有序的。

2、兩種排序方法:

(1)自定義一個比較器類,比如class Com implementsComparator{ }  ,實現compare(Object o1, Object o2)方法,在其中定義比較規則。

(2)讓元素自身具備比較性。
步驟:將add進TreeSet中的元素實現Comparable介面,並且覆蓋compareTo方法。這種順序也是元素的自然順序,或者叫做預設順序。

方法1和方法2的區別:

兩種方法各有優劣, 用Comparable 簡單, 只要實現Comparable 介面的物件直接就成為一個可以比較的物件,但是需要修改原始碼。

       用Comparator 的好處是不需要修改原始碼, 而是另外實現一個比較器, 當某個自定義的物件需要作比較的時候,把比較器和物件一起傳遞過去就可以比大小了, 並且在Comparator 裡面使用者可以自己實現複雜的可以通用的邏輯,使其可以匹配一些比較簡單的物件,那樣就可以節省很多重複勞動了。


(2)使用HashSet來實現

package com.package1;

import java.util.*;




public class StuScore {

	public static void main(String[] args) {
		
		HashSet<Student> hs=new HashSet<Student>();
		//新增元素進去
		for(int i=20070301,j=1;i<=20070330;i++,j++)
		{
		
			hs.add(new Student(i,"同學"+j,(int) 

(40*Math.random()+60)));
		}
		
		ArrayList<Student>li=new ArrayList(hs);
		
		Collections.sort(li, new Sortbygrade());
		
		for(Student ss:li)
			System.out.println(ss);
		

	}

}
//學生類
class Student 
{
	int num;
	int grade;
	String name;

	
	public Student(int num, String name, int grade)
	{
		this.num=num;
		this.name=name;
		this.grade=grade;
	}
	public String toString(){
		//System.out.println("hi");
		return "學號:"+this.num+"\t"+"姓名:"+this.name

+"    "+"成績:"+this.grade;
	}
	
	
}


class Sortbygrade implements Comparator{

	@Override
	public int compare(Object o1, Object o2) {
		
		Student s1=(Student) o1;
		Student s2=(Student) o2;
		if(s1.grade>s2.grade)
			return 1;
		if(s1.grade<s2.grade)
			return -1;
//		if(s1.grade==s2.grade)
		
		return 0;
	}
	
}

輸出結果如下:

學號:20070310姓名:同學19    成績:60
學號:20070330姓名:同學39    成績:62
學號:20070326姓名:同學35    成績:63
學號:20070317姓名:同學26    成績:64
學號:20070318姓名:同學27    成績:65
學號:20070322姓名:同學31    成績:65
學號:20070301姓名:同學10    成績:67
學號:20070328姓名:同學37    成績:68
學號:20070304姓名:同學13    成績:68
學號:20070319姓名:同學28    成績:69
學號:20070313姓名:同學22    成績:70
學號:20070303姓名:同學12    成績:71
學號:20070312姓名:同學21    成績:71
學號:20070329姓名:同學38    成績:72
學號:20070306姓名:同學15    成績:72
學號:20070324姓名:同學33    成績:72
學號:20070305姓名:同學14    成績:75
學號:20070315姓名:同學24    成績:75
學號:20070314姓名:同學23    成績:78
學號:20070307姓名:同學16    成績:80
學號:20070311姓名:同學20    成績:81
學號:20070302姓名:同學11    成績:83
學號:20070309姓名:同學18    成績:84
學號:20070320姓名:同學29    成績:85
學號:20070321姓名:同學30    成績:85
學號:20070316姓名:同學25    成績:86
學號:20070327姓名:同學36    成績:90
學號:20070308姓名:同學17    成績:94
學號:20070323姓名:同學32    成績:94
學號:20070325姓名:同學34    成績:95 對HashSet的總結:

1、HashSet中的元素不可以重複,如果重複新增,則只會顯示一個。

原理如下:

HashSet:底層資料結構是雜湊表。是執行緒不安全的。不同步。

2、HashSet是如何保證元素唯一性的呢?
答:是通過元素的兩個方法,hashCode和equals來完成。
如果元素的HashCode值相同,才會判斷equals是否為true。如果元素的hashcode值不同,不會呼叫equals。

3、對HashSet的排序,通過將Set集合轉化為List集合,藉助Collections.Sort( )方法實現排序。

3、使用TreeMap來實現

package com.package1;



import java.util.Comparator;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeMap;

public class TestTreeMap {

	public static void main(String[] args) {
		//1.建立集合
		TreeMap<Student,Integer> tm=new TreeMap<Student,Integer>();
		for(int i=20070301,j=10;i<=20070330;i++,j++)
		{
			int grade=(int) (40*Math.random()+60);
			 //2、往集合物件中新增元素
			 tm.put(new Student(grade,"同學"+j),i);
		}
		
		//3.遍歷集合 ,排序完成	
		Set<Student> k=tm.keySet();
		Iterator<Student> it=k.iterator();
		
		while(it.hasNext()){
			Student key=it.next();
			Integer num=tm.get(key);
			
			System.out.println("學號:"+num+"    "+"姓名:"+key.name+"    "+"成績:"+key.grade);
		}
	}

}

class Student implements Comparable<Student>{
	int grade;
	String name;
	
	public Student(int grade,String name){
		this.grade =grade;
		this.name=name;
	}

	@Override
	public int compareTo(Student o) {
		
		if(this.grade>o.grade)  
			return 1;  
			if(this.grade==o.grade)  
			{  //當成績相同時,按照姓名排序
			 return this.name.compareTo(o.name);  
			}  
			return -1;  

	}
	

	
}
輸出結果為:

學號:20070303    姓名:同學12    成績:61
學號:20070323    姓名:同學32    成績:61
學號:20070317    姓名:同學26    成績:62
學號:20070309    姓名:同學18    成績:64
學號:20070301    姓名:同學10    成績:67
學號:20070304    姓名:同學13    成績:69
學號:20070322    姓名:同學31    成績:69
學號:20070328    姓名:同學37    成績:70
學號:20070305    姓名:同學14    成績:71
學號:20070319    姓名:同學28    成績:73
學號:20070321    姓名:同學30    成績:74
學號:20070310    姓名:同學19    成績:81
學號:20070315    姓名:同學24    成績:82
學號:20070307    姓名:同學16    成績:84
學號:20070330    姓名:同學39    成績:84
學號:20070312    姓名:同學21    成績:85
學號:20070324    姓名:同學33    成績:87
學號:20070306    姓名:同學15    成績:88
學號:20070308    姓名:同學17    成績:90
學號:20070327    姓名:同學36    成績:90
學號:20070318    姓名:同學27    成績:91
學號:20070316    姓名:同學25    成績:92
學號:20070320    姓名:同學29    成績:92
學號:20070314    姓名:同學23    成績:93
學號:20070313    姓名:同學22    成績:94
學號:20070302    姓名:同學11    成績:95
學號:20070325    姓名:同學34    成績:95
學號:20070329    姓名:同學38    成績:97
學號:20070326    姓名:同學35    成績:98
學號:20070311    姓名:同學20    成績:99


對TreeMap的總結:

1、TreeMap預設對key進行排序,所以可將自定義物件放入key中,將代表學號的整型放入value中。對Key排序時,可以指定自定義物件中的某個屬性來排序。

2、Map集合使用put()方法新增元素。

3、Map集合的取出原理:將map集合轉成set集合。在通過迭代器取出。

map集合的兩種取出方式:

(1)Set<k> keySet:將map中所有的鍵存入到Set集合。因為set具備迭代器。
所有可以迭代方式取出所有的鍵,在根據get方法。獲取每一個鍵對應的值。

(2)Set<Map.Entry<k,v>> entrySet:將map集合中的對映關係存入到了set集合中,
而這個關係的資料型別就是:Map.Entry