Generics(泛型)&Collection(集合;收集)=>在java.util
●collection=>List-ArrayList( 和陣列一模一樣 )
-LinkedList
=>Set-HashSet(雜湊)
-sort(介面)-TreeSet
**說明
1.List是有順序的,有索引碼,先key先排,可重複資料
2.Set是亂數排序,不允許重複
3.collection、List、Set都是interface
4.sort提供順序
5.Treeset=>資料不允許重複,但有順序
(一)Generics(泛型)
1.不定類型
2.<T,E,....>
=>T,E=> 任意英文代號
3.限定使用"WRAPPER"類別與"class"
4.可以用在field、建構式、method
(當要讓使用者在新增時才決定類別時使用)
class Book<T>{
String bookname;
T bookprice;
Book(String bookname, T bookprice){
this.bookname=bookname;
this.bookprice=bookprice;
}
void show(){
System.out.println("書名:"+bookname+"\t價格:"+bookprice);
}
}
**說明:
1.如果使用者希望價格有時候可以輸入double有時候可以輸入int,改用泛型
2.new的時候由使用者自己定義類型
3.在class name後面寫<任意英文>,要使用泛型的地方都要放一樣的代號
class add1{
public static void main(String args[]){
Book<T> b1=new Book<T>("Java",380);
}
}
**說明:
1.如果在new的時候直接在class name後面加上<T>,會出現如上錯誤
2.代表java無法判斷如何新增內容,因為不知道380在這邊應該是甚麼類型,但詳細說明要重新編譯用javac -Xlint add1.java來看,詳細內容如下
3.所以將<T>改為<int>,設定使用者要用int,卻出現錯誤訊息如下,因為需要使用reference=>代表要用class,int是基本類別只能定義變數,要使用wrapper類別(ex:Double,Integer...)才能當作reference,因為wrapper類別既代表整數又有class身分
正確做法
class add1{
public static void main(String args[]){
Book<Integer> b1=new Book<Integer>("Java",380);
Book<Double> b2=new Book<Double>("android",650);
b1.show();
b2.show();
}
**說明:
但在這邊要注意,如果使用Double這個wrapper類別,輸入時就一定要使用浮點數,不然會出現錯誤訊息,不像基本類別的double可以接受整數
class add1{
public static void main(String args[]){
Book<Integer> b1=new Book<Integer>("Java",380);
Book<Double> b2=new Book<Double>("android",650.3);
b1.show();
b2.show();
}
}
多個不定類型時的用法
class Book<T,E>{
String bookname;
T bookprice;
E x;
Book(String bookname, T bookprice, E x){
this.bookname=bookname;
this.bookprice=bookprice;
this.x=x;
}
void show(){
System.out.println("書名:"+bookname+"\t價格:"+bookprice);
}
}
class add1{
public static void main(String args[]){
Book<Integer,Double> b1=new Book<Integer,Double>("Java",380,6.2);
Book<Double,Integer> b2=new Book<Double,Integer>("android",650.3,50);
}
}
另外,java7以後改成前面不寫,只寫後面也可以
class add1{
public static void main(String args[]){
Book b1=new Book<Integer,Double>("Java",380,6.2);
Book b2=new Book<Double,Integer>("android",650.3,50);
}
}
(二) Collection
1.解決"陣列"數量無法增加的問題
2.將"資料結構"應用寫成"API"應用
3.需搭配"泛型"為"reference"
4.語法:( 收集資料的方式/集合方式要先決定 )
集合方式<類型> 集合物件=new 集合方式<類型>();
=>集合物件指動態陣列
a) ArrayList
import java.util.ArrayList;
class add2{
public static void main(String args[]){
ArrayList<Integer> x=new ArrayList<Integer>();
x.add(110);
x.add(20);
x.add(30);
x.add(30);
for(Integer o:x){
System.out.println(o);
}
System.out.println("=============");
x.add(20);
x.add(650);
for(Integer o:x){
System.out.println(o);
}
}
}
**說明:
*注意:這邊x的類型是Integer而非 ArrayList, ArrayList是收集資料的方式
1.add()這個方法是從collection繼承給下面所有不同的收集方式,所以全部都可用add()來新增資料
新增資料的方式用add(E)=>看要使用的類型來決定輸入的類型,如上述就是Integer
2.輸入的資料無限制筆數且可重複
3. ArrayList 輸出時的排列方式為,先打進去的資料會排前面
4.ArrayList不能用.length會出現錯誤訊息,所以我們要一個個顯示資料可以用foreach的方式,如果要計算陣列個數則可以用迴圈和count++來做
5.可重複,所以有兩個30
6.可事後增加數量,所以第二次的輸出多兩個內容
7.如果要查記憶體位置,要用x.iterator();這個方法,結果如下:
LinkedList
import java.util.ArrayList;
import java.util.LinkedList;
class add2{
public static void main(String args[]){
LinkedList<Integer> x=new LinkedList<Integer>();
x.add(110);
x.add(20);
x.add(30);
x.add(30);
for(Integer o:x){
System.out.println(o);
}
System.out.println("=============");
x.add(20);
x.add(650);
for(Integer o:x){
System.out.println(o);
}
System.out.println(x.iterator());
}
}
**說明:
1.要先import class進來
2.輸出結果完全一樣,只有收集資料的方式不同
3. LinkedList和ArrayList差別在於,前者除了list還有一個Queue interface,用途是為了能解省記憶體,但因為java不太管效能,所以很少用
HashSet
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.HashSet;
class add2{
public static void main(String args[]){
HashSet<Integer> x=new HashSet<Integer>();
x.add(110);
x.add(20);
x.add(30);
x.add(30);
for(Integer o:x){
System.out.println(o);
}
System.out.println("=============");
x.add(20);
x.add(650);
for(Integer o:x){
System.out.println(o);
}
System.out.println(x.iterator());
}
}
**說明:
順序亂數排列,且不重複
TreeSet
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.HashSet;
import java.util.TreeSet;
class add2{
public static void main(String args[]){
TreeSet<Integer> x=new TreeSet<Integer>();
x.add(110);
x.add(20);
x.add(30);
x.add(30);
for(Integer o:x){
System.out.println(o);
}
System.out.println("=============");
x.add(20);
x.add(650);
for(Integer o:x){
System.out.println(o);
}
System.out.println(x.iterator());
}
}
**說明:
由小到大重新排列,且不重複
實作
這次要收集的資料類型是一整張表的資料,而非只有integer或double,所以資料類型變成student class(student類型的資料)
(一)ArrayList和 LinkedList
import java.util.ArrayList;
import java.util.LinkedList;
class student {
private String name;
private int chi;
private int eng;
student(String name,int chi,int eng){
this.name=name;
this.chi=chi;
this.eng=eng;
}
void show(){
System.out.println("名字:"+name+"\t國文:"+chi+"\t英文:"+eng);
}
class add3{
public static void main(String args[]){
//ArrayList<student> s=new ArrayList<student>();
LinkedList<student> s=new LinkedList<student>();
s.add(new student("aa",85,77));
s.add(new student("aa1",85,77));
s.add(new student("aa2",86,78));
for (student o:s){
o.show();
}
}
}
**說明:
1.用 ArrayList和 LinkedList輸出結果相同
2. 在new的時候,這邊變成要新增一個學生物件 new student("aa",85,77) ,而非一個值
3. foreach的類型也要是student,因要和s同樣類型, 因為把s指給o,所以o也是一個物件,可以直接用o.show()
(二)用HashSet,資料不重複
class add3{
public static void main(String args[]){
HashSet<student> s=new HashSet<student>();
s.add(new student("aa",85,77));
s.add(new student("aa1",87,97));
s.add(new student("aa2",83,67));
for (student o:s){
o.show();
}
}
}
**說明:
1.用 HashSet亂數排序
2. 是否重複是看記憶體位置,只要有new就不會重複記憶體位置
(三)用HashSet,資料重複
class add3{
public static void main(String args[]){
HashSet<student> s=new HashSet<student>();
s.add(new student("aa",85,77));
s.add(new student("aa",85,77));
s.add(new student("aa",85,77));
for (student o:s){
o.show();
}
}
}
**說明:
因為HashSet判斷是否重複是由記憶體位址來判斷,而非由輸入的值來判斷,所以還是會有三筆資料
(四)用TreeSet
class add3{
public static void main(String args[]){
TreeSet<student> s=new TreeSet<student>();
s.add(new student("aa",85,77));
s.add(new student("aa",85,77));
s.add(new student("aa",85,77));
for (student o:s){
o.show();
}
}
}
**說明:
1.改用TreeSet,可以compiler但是執行出現Exception
2.因為這邊是物件無法直接排序,要排序的話要由現有的欄位中抓一個欄位當作索引欄位(要告訴他要由哪個欄位來排順序)
正確做法:
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.HashSet;
import java.util.TreeSet;
class student implements Comparable<student>{
private String name;
private int chi;
private int eng;
student(String name,int chi,int eng){
this.name=name;
this.chi=chi;
this.eng=eng;
}
void show(){
System.out.println("名字:"+name+"\t國文:"+chi+"\t英文:"+eng);
}
public int compareTo(student o){
return this.chi-o.chi;
}
}
class add3{
public static void main(String args[]){
TreeSet<student> s=new TreeSet<student>();
s.add(new student("aa",85,77));
s.add(new student("aa",85,77));
s.add(new student("aa",85,77));
for (student o:s){
o.show();
}
}
}
**說明:
1. 要繼承comparable interface(用implements),<>中要放要排序的類型物件,因為comparable是泛型
2.因為繼承interface的compareTo()方法,所以要override,故前面要加public和繼承的int,copareTo()裡面要放本身物件(student),和下一個物件(o)
3.return時,this是物件本身,o是指下一個物件,這邊要指定欄位用國文分數(chi),
4.語法:this-o,如果:>0由小到大排列,<0由大到小排列,=0不變
5.通常當主索引欄不會重複且可以判斷先後順序者,會用TreeSet來做
6. TreeSet排列是用指定的欄位值來判斷,這邊指定國文分數來判斷,此時三者相同,所以判斷重複,最後會輸出一筆
7.如果改為如下,就會輸出三筆並且照國文分數由小到大排列
s.add(new student("aa",86,77));
s.add(new student("aa",88,77));
s.add(new student("aa",85,77));
●泛型與多型應用
1.泛型
2.多型
=>陣列:數量無法增加;集合:可增加(又稱為動態陣列)
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.HashSet;
import java.util.TreeSet;
class student implements Comparable<student>{
private String name;
private int chi;
private int eng;
student(String name,int chi,int eng){
this.name=name;
this.chi=chi;
this.eng=eng;
}
void show(){
System.out.print("名字:"+name+"\t國文:"+chi+"\t英文:"+eng);
}
public int compareTo(student o){
return this.chi-o.chi;
}
}
class A extends student{
private int word;
A(String name,int chi, int eng ,int word){
super(name,chi,eng);
this.word=word;
}
void show(){
super.show();
System.out.println("\tword:"+word);
}
}
class B extends student{
private int excel;
B(String name,int chi, int eng ,int excel){
super(name,chi,eng);
this.excel=excel;
}
void show(){
super.show();
System.out.println("\texcel:"+excel);
}
}
class add3{
public static void main(String args[]){
ArrayList<student> s=new ArrayList<student>(); //定義父類別(的資料收集方法)
s.add(new A("aa",86,77,88)); //new子類別
s.add(new A("aa2",88,77,76));
s.add(new B("bb",85,77,87));
for (student o:s){
o.show();
}
System.out.println("=============");
s.add(new A("aa3",67,87,96));
s.add(new B("bb2",73,84,97));
for (student o:s){
o.show();
}
}
}
**說明:
1.在做輸入資料的介面時不可能鎖死資料筆數,所以要用集合不能用陣列
2.這邊只要A和student有繼承關係就能 s.add(new A("aa",86,77,88));
3. for (student o:s)=>forecach的reference還是看student,因為s的reference是student
4.和多型一樣,也是先定義父類別然後new子類別
5.做法和陣列完全一樣,只是改為集合,數量可以增加,陣列的作法為
student s(定義父類別)={new A("aa3",67,87,96),new B("bb2",73,84,97)};(new子類別)
6.可以事後增加資料
7. 此時還沒有索引碼,所以還沒辦法直接用索引碼找資料
3.先用集合建立,再透過Object[]陣列=>集合toArray(); (不一定要做這個步驟)
=>轉回陣列=>製作索引碼
class add3{
public static void main(String args[]){
ArrayList<student> s=new ArrayList<student>();
s.add(new A("aa",86,77,88));
s.add(new A("aa2",88,77,76));
s.add(new B("bb",85,77,87));
Object[] x=s.toArray();
System.out.println(x[0]); //輸出記憶體位址
//x[0].show(); //出現如下錯誤
((student)(x[0])).show();
}
}
**說明:
1.要把s集合的內容轉為x陣列
2.toArray()會轉成物件類型Obtect class(所有class的共同父類別)
3.如果直接用x[0].show()會找不到,因為編譯時會先去x找show()方法,但x是Object類型,會找不到
4.要把x[0]轉型為student類型(toArray一開始會先把類別拉到最上層(即所有class的父類別Object),所以要再降為目前的類型),把 x[0].show();改為((student)(x[0])).show();即可
文章標籤
全站熱搜
留言列表