1,集合類
爲什麼出現集合類?
面嚮對象語言對實物的體現都是以對象的形式,所以爲了方便對多個對象的操作,就對對象進行存儲,集合就是存儲最常用的一種方式。
集合和集合類同時容器,有何不同?
數組雖然也可以存儲對象,但長度是固定的,集合長度是可變的
數組中可以存儲基本數據類型,集合只能存儲對象。
集合類的特點
集合只用於存儲對象,集合的長度是可變的,集合可以存儲不同類型的對象。
2,集合的學習體系:
---- |Colleciton 描述所有接口的共性
------|List可以有重複元素的集合
------|Set 不能有重複元素的集合
3,Collection 常用方法
1增加:
add();將指定的對象存儲到集合容器中
addAll() 將指定集合中的元素添加到調用方法集合中
2,刪除
remove()將指定集合元素添加到調用該方法的集合中。
removeAll()將指定集合中的元素刪除
3,修改:
clear()清空集合中的所有元素
4,判斷
isEmpty() 判斷集合是否爲空
contains()判斷集合中是否包含指定對象 使用equals()判斷兩個對象是否相等
containsAll(0判斷集合中是否包含指定集合 使用equals()判斷兩個對象是否相等。
5,獲取
size()返回集合容器的大小
6,查看集合裏面的所有元素轉換方法:
toArray()返回包含collection中所有元素的數組
7,Iterable迭代器 該類主要用來便利集合對象,該類描述了遍歷集合的常用迭代方法。
1,hashNext()如果有元素可以迭代,就返回true;
2,next()返回下一個元素。如果沒有下一個元素,調用元素會拋出NoSuchElementExcepton
3,remover()從迭代器指向的集合中移除迭代器返回的最後一個元素
4,迭代器 遊戲或指針,其實就是調用了ArrayList.get() index++;
import java.util.ArrayList;
public class Test1 {
public static void main(String[] args) {
ArrayList a1 = new ArrayList();
// 添加元素
a1.add("java01");// add(Object obj);
a1.add("java02");
a1.add("java03");
sop(a1);
a1.remove("java02");// 刪除元素
a1.clear();// 清除元素
sop("java03是否存在" + a1.contains("java01"));
sop("集合是否爲空?" + a1.isEmpty());
// 獲取長度
sop("size" + a1.size());
}
public static void sop(Object obj) {
System.out.println(obj);
}
}
import java.util.ArrayList;
import java.util.Iterator;
/*
* 什麼是迭代器
* 其實就是集合的取出元素的方式。
*/
public class Test2 {
public static void main(String[] args) {
method_get();
}
public static void method_get() {
ArrayList a1 = new ArrayList();
// 添加元素
a1.add("java01");// add(Object obj);
a1.add("java02");
a1.add("java03");
Iterator it = a1.iterator();// 獲取迭代器,用於取出集合中的元素
while (it.hasNext()) {
sop(it.next());
}
}
public static void sop(Object obj) {
System.out.println(obj);
}
}
4,List
1,獲取
1,get(int index);
注意:IndexOutOfBoundsExcepton;
2,修改
set(int index,E element);
3,查找:
int indexOf(Object);//找不到返回-1;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/*
* Collection
* |--List:元素是有序的,元素可以重複,因爲該集合體繫有索引
* |--Set :元素無序,元素不可以重複
* List
* 本身也是一個抽取出來的接口
* 特有方法:凡是可以操作角標的方法都是該體系特有的方法
* 增
* add(index,element);
* addAll(index,Collection);
* 刪
* remove(index);
* 改
* set(index,elemet);
* 查
* get(index);
* subList(from,to);
* listIterator();
*/
public class Test3 {
public static void sop(Object obj) {
System.out.println(obj);
}
public static void main(String[] args) {
ArrayList a1 = new ArrayList();
a1.add("java01");
a1.add("java02");
a1.add("java03");
sop("源集合是" + a1);
a1.add(1, "java09");// 添加指定位置
a1.remove(2);// 刪除指定位置的元素
// 修改元素
a1.set(2, "java07");
// 通過角標獲取元素
sop("get(1):" + a1.get(1));
// 獲取所有元素
for (int x = 0; x < a1.size(); x++) {
System.out.println("a1" + a1.get(x));
}
Iterator it=a1.iterator();
while(it.hasNext()){
sop("next:"+it.next());
}
sop("index"+a1.indexOf("java02"));
List sub=a1.subList(1, 3);//包含1不包含3
sop("sub"+sub);
}
}
刪除list集合重複的值。
import java.util.ArrayList;
public class Test{
public static void main(String[] args) {
ArrayList list = new ArrayList();
//list.add("abc");
list.add("adb");
list.add("abc");
list.add("abc");
list.add("adb");
list.add("abc");
System.out.println(list.size());
//int size = list.size();
for (int x = 0; x < list.size(); x++){//循環
String str = (String)list.get(x);
if (str.equals("abc")) {//判斷條件
list.remove(x);
// list.remove(0);
System.out.println("--還剩下"+list.size()+".."+x);
x=-1;//集合的長度在不斷的變化,所以這裏要是x=-1;
}
}
System.out.println(list);
System.out.println(list.size());
}
}
5,ArrayList,LinkedList比較
2, ArrayList 實現List接口
3,LinkedList
1,查找元素慢,出入和刪除快。
4,ArrayList和LinkedList的存儲查找的優點和缺點
1,ArrayList是採用動態數組來存儲元素的,它允許直接下標號直接查找對應的元素。
但是,插入元素要涉及數組元素移動及內存的操作。總結:查找速度快,插入操作忙。
2,LindedList 是採用雙向鏈表示實現存儲,按序號索引數據需要進行前向或後向便利
但是插入數據的時,只需要記錄本項前後項即可,所以插入速度快。
import java.util.LinkedList;
public class Test4 {
public static void main(String[] args) {
LinkedList link = new LinkedList();
link.addFirst("java01");// linklist特有方法
link.addFirst("java02");
link.addFirst("java03");
link.addFirst("java04");
link.addLast("java05");
sop(link);
sop(link.getFirst());// 不刪除獲取
sop(link.getLast());
sop(link.remove());// 獲取並刪除
sop(link.size());
}
public static void sop(Object obj) {
System.out.println(obj);
}
}
6,Set
Set:元素是無序(存入和取出的順序不一定一致),元素不可以重複
Set:集合的功能和Collection是一致的。
1,問題:有一批數據要存儲,要求存儲這批數據不能出現重複數據,ArrayList,LinkedList都沒法滿足需求
解決方法:Set集合
2,set集合特點:無序。不能有重複元素的集合
3,HashSet:數據結構是哈希表,線程是非同步的
哈希表是按照哈希值來存儲的
不是同一對象,但是地址值是一樣的,這個時候他會在該地址值下順延。
保證元素唯一性的原理:判斷元素的hashCode值是否相同
如果相同,還會繼續判斷元素的equals方法,是否爲true;添加失敗就爲假。
HashSet是如何保證元素唯一性的呢?
是通過元素的兩個方法,hashCode和equals來完成。
如果元素的HashCode值相同,纔會判斷euqals是否爲true,如果元素的hashscode值不同,不會調用equals.(建立一個比較有針對性的hashcode會比較高效一些)
import java.util.HashSet; import java.util.Iterator;
/** * HashSet存儲自定義對象 * * @author Administrator 網hashset存入自定義對象,姓名和年齡相同爲同一個人,重複元素 */ public class Test { public static void main(String[] args) { HashSet hs = new HashSet(); //添加person對象 hs.add(new Person("a1", 11)); hs.add(new Person("a2", 12)); hs.add(new Person("a3", 13)); hs.add(new Person("a2", 12)); //hs.add(new Person("a4", 14)); Iterator it = hs.iterator();//迭代器對象 //遍歷 while (it.hasNext()) { Person p = (Person) it.next();//強制類型轉換 sop(p.getName()+"::"+p.getAge()); } } /** * 打印方法 * @param obj */ public static void sop(Object obj) { System.out.println(obj); } } /** * person類,名字年齡 * @author Administrator * */ class Person { private String name;
public String getName() { return name; }
public int getAge() { return age; }
private int age;
Person(String name, int age) { this.name = name; this.age = age; } //重寫equals方法 public boolean equals(Object obj) { if (!(obj instanceof Person)) { return false; } Person p = (Person) obj; return this.name.equals(p.name) && this.age == p.age; } }
以上打印結果爲: a2::12
a1::11
a2::12
a3::13
equals沒有被調用。因爲比較先看地址。new 出來的,都有自己獨立的hashcode,有自己的位置存儲,都存進去了,不用再讀equals方法了。
現在要覆蓋Person 的hashcode方法,建立Person對象自己的哈希值。怎麼建立哈希值呢?你的判斷條件是什麼,依據條件來生成哈希值,這裏按照姓名年齡判斷是不是同一個元素,那就依據這個條件判斷哈希值。
import java.util.HashSet; import java.util.Iterator; /** * HashSet存儲自定義對象 * * @author Administrator 網hashset存入自定義對象,姓名和年齡相同爲同一個人,重複元素 */ public class Test2 { public static void main(String[] args) { HashSet hs = new HashSet(); hs.add(new Person("a1", 11)); hs.add(new Person("a2", 12)); hs.add(new Person("a3", 13)); hs.add(new Person("a2", 12)); //hs.add(new Person("a4", 14)); Iterator it = hs.iterator(); while (it.hasNext()) { Person p = (Person) it.next(); sop(p.getName()+"::"+p.getAge()); } } public static void sop(Object obj) { System.out.println(obj); } } class Person { private String name; public String getName() { return name; } public int getAge() { return age; } private int age; Person(String name, int age) { this.name = name; this.age = age; } public int hashCode(){ System.out.println(this.name+"....hashcode"); //按照條件設置hashcode return name.hashCode()+this.age*39;//39沒有特殊意思,也可以是其他,容易導致hashcode相同,儘量保持哈希值的唯一 //不科學的比較方式 return 60; } public boolean equals(Object obj) { if (!(obj instanceof Person)) { return false; } Person p = (Person) obj; System.out.println(this.name+".euqals.."+p.name); return this.name.equals(p.name) && this.age == p.age; } }
科學的打印
a1....hashcode
a2....hashcode
a3....hashcode
a2....hashcode
a2.euqals..a2
a2::12
a3::13
a1::11
非科學打印結果爲
a1....hashcode
a2....hashcode
a2.euqals..a1
a3....hashcode
a3.euqals..a2
a3.euqals..a1
a2....hashcode
a2.euqals..a3
a2.euqals..a2
a3::13
a2::12
a1::11
HashSet判斷和刪除的依據
注意:對於判斷元素是否存在,以及刪除等操作,依賴的方法是元素的hashCode和equals方法。先判斷hashCode,hashcode如果有的話, 再判斷equals.
import java.util.HashSet; import java.util.Iterator;
/** * HashSet存儲自定義對象 * * @author Administrator 網hashset存入自定義對象,姓名和年齡相同爲同一個人,重複元素 */ public class Test { public static void main(String[] args) { HashSet hs = new HashSet(); hs.add(new Person("a1", 11)); hs.add(new Person("a2", 12)); hs.add(new Person("a3", 13)); hs.add(new Person("a2", 12)); //hs.add(new Person("a4", 14)); sop(hs.contains(new Person("a1",11))); hs.remove(new Person("a1",11)); Iterator it = hs.iterator(); while (it.hasNext()) {//迭代器迭代 Person p = (Person) it.next(); sop(p.getName()+"::"+p.getAge()); } } //打印 public static void sop(Object obj) { System.out.println(obj); } }
class Person { private String name;
public String getName() { return name; }
public int getAge() { return age; }
private int age;
Person(String name, int age) { this.name = name; this.age = age; } //重寫hashCode方法 public int hashCode(){ System.out.println(this.name+"....hashcode"); //按照條件設置hashcode return name.hashCode()+this.age*39;//39沒有特殊意思,也可以是其他,容易導致hashcode相同,儘量保持哈希值的唯一 //不科學的比較方式 return 60; } //重寫equals方法 public boolean equals(Object obj) { if (!(obj instanceof Person)) { return false;//如果不是Person的實例,返回false; } Person p = (Person) obj; System.out.println(this.name+".euqals.."+p.name); return this.name.equals(p.name) && this.age == p.age;//比較年齡和名字 } }
ArrayList判斷元素是否存在,和刪除元素只依賴於equals,而hashSet依賴於hashCode和equals4TreeSet:可以對set集合中的元素進行排序。自然順序ASCII表
import java.util.Iterator; import java.util.TreeSet; /** * 可以對Set集合中的元素進行排序。Ascii排序 * * @author Administrator * */ public class Test4 { public static void main(String[] args) { TreeSet ts = new TreeSet(); ts.add("abcd"); ts.add("abcg"); ts.add("aaaa"); ts.add("bca"); Iterator it = ts.iterator(); while (it.hasNext()) { System.out.println(it.next());// 跟存的順序不一樣但是打印的時候有自己的順序 // 打印結果aaaa // abcd // abcg // bca } } }
底層數據結構是二叉樹
保證元素的唯一性的依據
compareTo方法return 0,返回0認爲元素相同,否則都不相同
排序的第一種方式:讓元素自身具備比較性,讓元素自身具備比較性。
元素需要實現Compaable接口,覆蓋compareTo方法,這種方式稱爲元素的自然順序,或者叫做默認順序,一被定義出來就具備比較性
排序的第二種方式:當元素自身不具備比較性時,或者具備的比較性不是所需要的,這時就需要讓集合自身具備比較性。
存儲自定義對象
import java.util.Iterator;
import java.util.TreeSet;
/**
* 存儲之定義對象
* 往TreeSet集合中存儲自定義對象
* 想按照學生的年齡進行排序
* @author Administrator
*
*/
public class Test4 {
public static void main(String[] args) {
TreeSet ts = new TreeSet();
ts.add(new Student("lisi02", 22));
ts.add(new Student("lise007", 20));
ts.add(new Student("lise09", 22));
ts.add(new Student("lise01", 22));
Iterator it = ts.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
class Student {
private String name;
private int age;
public int getAge() {
return age;
}
Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
}
類型轉換異常,學生不能不能被轉換java.lang.Comparable
Comparable接口強行對實現它的每個類的對象進行整體排序。這種排序被稱爲類的自然排序,類的compareTo方法被稱爲自然比較法。
以上例子,存儲一個對象,就沒有異常,再存就出現了異常。。TreeSet集合能排序,可是按照什麼方式排呢?學生對象不具備比較性。所以java說,你必須要讓你的元素具備比較性。TreeSet集合的要求是,往裏面存的集合必須具備比較性。怎麼具備比較性呢?
import java.util.Iterator;
import java.util.TreeSet;
/**
* 存儲之定義對象
* 往TreeSet集合中存儲自定義對象
* 想按照學生的年齡進行排序
* @author Administrator
*
*/
public class Test4 {
public static void main(String[] args) {
TreeSet ts = new TreeSet();
ts.add(new Student("lisi02", 22));
ts.add(new Student("lise007", 20));
ts.add(new Student("lise09", 19));
// ts.add(new Student("lise01", 22));
Iterator it = ts.iterator();
while (it.hasNext()) {
Student stu=(Student)it.next();
System.out.println(stu.getName()+"..."+stu.getAge());
}
}
}
class Student implements Comparable {//該類接口強制讓學生具備比較性
private String name;
private int age;
public int getAge() {
return age;
}
Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
@Override
public int compareTo(Object obj) {
// TODO Auto-generated method stub
if(!(obj instanceof Student)){
throw new RuntimeException("不是學生對象");
}
Student s=(Student)obj;
System.out.println(this.name+"...........compareto........"+s.name);
if(this.age>s.age){//此對象大於指定對象返回正數
return 1;
}else if(this.age==s.age){
return 0;
}
return -1;
}
}
但是以上的代碼還是有問題的。如果再添加一個年齡相同的對象,則發現打印 的時候少了一個對象。當他們年齡相等的時候,compareTo返回0.
代表此對象與指定對象是相同的。就沒有存進去。在本例中,年齡相同,姓名也相同纔是同一個人。毫無疑問,判斷完年齡後,再判斷一下姓名。當主要條件相同時,要排序次要條件排。次要條件相同,那就相同了。這裏要比較字符串,字符串具備比較行爲。String 類的compareTo(String anotherString)按照字典順序比較兩個字符串。
String類,本身就已經實現了Comparable.java中的很多對象都具備比較性。
記住:排序時,當主要條件相同時,一定判斷一下次要條件。
import java.util.Iterator;
import java.util.TreeSet;
/**
* 存儲之定義對象
* 往TreeSet集合中存儲自定義對象
* 想按照學生的年齡進行排序
* @author Administrator
*
*/
public class Test4 {
public static void main(String[] args) {
TreeSet ts = new TreeSet();
ts.add(new Student("lisi02", 22));
ts.add(new Student("lise007", 20));
ts.add(new Student("lise09", 19));
ts.add(new Student("lise10", 19));
// ts.add(new Student("lise01", 22));
Iterator it = ts.iterator();
while (it.hasNext()) {
Student stu=(Student)it.next();
System.out.println(stu.getName()+"..."+stu.getAge());
}
}
}
class Student implements Comparable {//該類接口強制讓學生具備比較性
private String name;
private int age;
public int getAge() {
return age;
}
Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
@Override
public int compareTo(Object obj) {
// TODO Auto-generated method stub
if(!(obj instanceof Student)){
throw new RuntimeException("不是學生對象");
}
Student s=(Student)obj;
System.out.println(this.name+"...........compareto........"+s.name);
if(this.age>s.age){//此對象大於指定對象返回正數
return 1;
}else if(this.age==s.age){
return this.name.compareTo(s.name);
}
return -1;
}
}
TreeSet 排序就是互相比較,元素越多,你互相比較的次數越多,效率很低。所以爲了優化效率,TreeSet用了一種特殊的數據結構。二叉樹,減少比較次數,提高比較性能。(小於的在左邊,大於的在右邊)
如果是降序,return 的值1變爲-1,都取反。
現在讓數據怎麼存進去的怎麼取出來。怎麼做呢?
在TreeSet比較對象的時候,和compareTo 方法中的if判斷是沒有關係的。只看結果,是正是負,是0,?直接return 1就可以實現。
排序的第二種方式:當元素自身不具備比較性時,或者具備的比較性不是所需要的,這時就需要讓集合自身具備比較性。
在集合初始化時,就有了比較方式。構造函數
定義比較器,將比較器對象作爲參數傳遞給TreeSet集合的構造函數。
第一種,讓元素具備比較性,第二種讓容器自身具備比較性。當兩種排序都存在時,以比較器爲主。
定義一個類。實現Comparator接口,覆蓋Compare方法
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
/**
* 存儲之定義對象
* 往TreeSet集合中存儲自定義對象
* 想按照學生的年齡進行排序
* @author Administrator
*
*/
public class Test4 {
public static void main(String[] args) {
TreeSet ts = new TreeSet(new MyCompares());
ts.add(new Student("lisi02", 22));
ts.add(new Student("lisi007", 20));
ts.add(new Student("lisi09", 19));
ts.add(new Student("lisi10", 19));
ts.add(new Student("lisi007", 20));
// ts.add(new Student("lise01", 22));
Iterator it = ts.iterator();
while (it.hasNext()) {
Student stu=(Student)it.next();
System.out.println(stu.getName()+"..."+stu.getAge());
}
}
}
class Student implements Comparable {//該類接口強制讓學生具備比較性
private String name;
private int age;
public int getAge() {
return age;
}
Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
@Override
public int compareTo(Object obj) {
// TODO Auto-generated method stub
if(!(obj instanceof Student)){
throw new RuntimeException("不是學生對象");
}
Student s=(Student)obj;
//System.out.println(this.name+"...........compareto........"+s.name);
if(this.age>s.age){//此對象大於指定對象返回正數
return 1;
}else if(this.age==s.age){
return this.name.compareTo(s.name);
}
return -1;
}
}
class MyCompares implements Comparator{
//這裏不用複寫equals方法了,因爲MyCompares繼承了Object了。已經有了equals
@Override
public int compare(Object o1, Object o2) {
// TODO Auto-generated method stub
Student s1=(Student)o1;
Student s2=(Student)o2;
int num= s1.getName().compareTo(s2.getName());
if(num==0){//主要條件相同,判斷次要條件
/*if(s1.getAge()>s2.getAge()){
return 1;
}
if(s1.getAge()==s2.getAge()){
return 0;
}
//return -1;*/
return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
}
return num;
}
}
以上就是排序的兩種方式。
實例:按照字符串長度進行比較
import java.util.HashSet;
import java.util.Iterator;
public class Test5 {
public static void main(String[] args) {
// Test5 t1=new Test5();
// Test5 t2=new Test5();
HashSet hs = new HashSet();
hs.add("javao1");// 返回true
hs.add("javao1");// 返回false;
hs.add("javao2");
hs.add("javao3");
Iterator it = hs.iterator();
while (it.hasNext()) {
sop(it.next());
}
}
public static void sop(Object obj) {
System.out.println(obj);
}
}
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
/* * 按照字符串長度排序TreeSet基本應用 */ public class Test6 { public static void main(String[] args) { TreeSet ts = new TreeSet(new StringLengthCommparator()); ts.add("abcd"); ts.add("cc"); ts.add("z"); ts.add("hahha"); Iterator it = ts.iterator(); while (it.hasNext()) { System.out.println(it.next()); } } }
class StringLengthCommparator implements Comparator {
@Override public int compare(Object o1, Object o2) { // TODO Auto-generated method stub String s1 = (String) o1; String s2 = (String) o2; /* * if(s1.length()>s2.length()){ return 1; } * if(s1.length()==s2.length()){ return 0; } */ int num = new Integer(s1.length()).compareTo(new Integer(s2.length())); if (num == 0) { return s1.compareTo(s2); } return num; }
}
|-- HashSet
|-- 底層是哈希表,不存儲重複元素
|-- 存儲自定義對象,需要覆蓋對象中的hashCode和equals方法,保證對象對象唯一
|-- TreeSet
|-- 底層是二叉樹結構,不存儲重複元素
|-- 存儲對象,按照對象的自然順序排序
|-- 自定義對象,必須具備比較性
|--對象本身具備比較性,實現Comparable接口,覆蓋compareTo方法
|--TreeSet本身具備比較性,自定義比較器,實現Comparator接口,覆蓋compare方法
7,泛型
1泛型的好處:
1,將運行時的異常提前至編譯時發生
2,使用get獲取元素的時候無需強類型轉型,就避免了類型轉換的異常問題
泛型的格式:通過<>來定義要操作的引用數據類型。
在使用java提供的對象時,什麼時候寫泛型呢?
通常在集合框架中很常見
只要見到<>就要定義泛型。
其實<>就是用來接收類型的。
當使用集合時,將集合中要存儲的數據類型做作爲參數傳遞到<>中即可。
上面的例子可以優化
import java.util.Comparator; import java.util.Iterator; import java.util.TreeSet; /** * 存儲之定義對象 * 往TreeSet集合中存儲自定義對象 * 想按照學生的年齡進行排序 * @author Administrator * */ public class Test4 { public static void main(String[] args) { TreeSet<Student> ts = new TreeSet<Student>(new MyCompares()); ts.add(new Student("lisi02", 22)); ts.add(new Student("lisi007", 20)); ts.add(new Student("lisi09", 19)); ts.add(new Student("lisi10", 19)); ts.add(new Student("lisi007", 20)); // ts.add(new Student("lise01", 22)); Iterator it = ts.iterator(); while (it.hasNext()) { Student stu=(Student)it.next(); System.out.println(stu.getName()+"..."+stu.getAge()); } } } class Student implements Comparable {//該類接口強制讓學生具備比較性 private String name; private int age; public int getAge() { return age; } Student(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } @Override public int compareTo(Object obj) { // TODO Auto-generated method stub if(!(obj instanceof Student)){ throw new RuntimeException("不是學生對象"); } Student s=(Student)obj; //System.out.println(this.name+"...........compareto........"+s.name); if(this.age>s.age){//此對象大於指定對象返回正數 return 1; }else if(this.age==s.age){ return this.name.compareTo(s.name); } return -1; } } class MyCompares implements Comparator<Student>{//定義泛型不用轉換了。 @Override public int compare(Student s1, Student s2) { // TODO Auto-generated method stub int num= s1.getName().compareTo(s2.getName()); if(num==0){//主要條件相同,判斷次要條件 return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge())); } return num; } }
以下是自定義泛型的示例
public class Test7 {
public static void main(String[] args) {
Tool<Worker> u=new Tool<Worker>();
u.setObject(new Worker());
Worker w=u.getObect();
}
}
class Worker{
}
class Student{
}
class Tool<QQ>{
private QQ q;
public void setObject(QQ q){
this.q=q;
}
public QQ getObect(){
return q;
}
}
什麼時候定義泛型類呢?
當類中要操作的引用數據類型不確定的時候,早期定義Object來完成擴展。
現在定義泛型來完成擴展。
泛型類定義的泛型,在整個類中有效,如果被方法使用,那麼泛型類的對象明確要操作的具體類型後,所有要操作的類型就已經固定了。
爲了讓不同方法可以操作不同類型,而且類型還不確定,那麼可以就將泛型定義在方法上。
class Demo{
public <T> void show(T t)
{
syso(t)
}
}
8,map
--|Map接口 將鍵映射到值得對象。一個映射不能包含重複的鍵;每個鍵最多隻能映射到一個值。
--|HashMap採用哈希表實現,所以無序
1,常見方法
添加
put(key,value);可以使用相同的key值,但是添加的value值會覆蓋前面的,返回值是前一個value。
//添加元素,如果出現相同的鍵,那麼後添加的值會覆蓋原有鍵對應的值。並put方法返回被覆蓋的值。
刪除
remove(key)刪除關聯對象,指定key對象
clear()清除集合對象
判斷
containsValue(Object value)
containsKey(Object key)
isEmpty()
獲取
get(Object key);
size()
value()
entrySet()
keySet()
2,遍歷方式
需要分別獲取key和value Set<> keySet()返回所有對象的Set集合
3,結構體系
|--Hashtable:底層是哈希表數據結構,不可以存入null鍵null值,該集合是線程同步的,用作鍵的對象,必須實現hashCode方法,和equals方法,該集合是元老級別的。效率低。
|--HashMap:底層是哈希表數據結構,並允許使用null鍵null值,該集合不同步的,效率高。
|--TreeMap:底層是二叉樹數據結構,線程不同步,,可以用於給map集合中的鍵進行排序
和set很像,Set底層就是使用了Map集合
Map.Entry其實Entry也是一個接口,它是Map接口中的一個內部接口。Map集合內部的事物,只有有了Map集合纔能有關係,Entry直接訪問Map集合中的元素。所以定義了內部規則。
public static interface Map.Entry<k,v>;能加static的接口一定是內部接口。只有接口在成員位置上,才能加上靜態修飾符。
interface Map{
public static interface Entry{
public abstract Object getKey();
public abstract Object getValue();
}
}
class HashMap implements Map.Entry{
public Object getKey();
public Object getValue();
}
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
public class Test8 {
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("01", "a1");
map.put("02", "a2");
map.put("03", "a3");
System.out.println("containsKey" + map.containsKey("022"));// false
System.out.println("remove" + map.remove("02"));// 返回移除的值
System.out.println("get:" + map.get("023"));// 判斷是否存在,返回null
map.put("04", null);// 空可以作爲鍵存在,Hashtbale不能空
System.out.println("get:" + map.get("04"));// 可以通過get方法的返回值來判斷一個鍵是否存在
// 獲取map集合中所有的值
Collection<String> coll = map.values();
System.out.println(coll);// 無序的
// map.put(key,value)返回這個鍵對應的原來的值,沒有返回null,存在則覆蓋原有鍵對應的值,put方法返回被覆蓋的值
System.out.println("put:" + map.put("05", "a5"));
}
}
keyset的示例
取出原理:將map集合轉成set集合。在通過迭代器取出。
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/*
* map集合的兩種取出方式
* 1,keySet:將map中所有的鍵存入到set集合。因爲set具備迭代器
* 所有可以迭代方式取出所有的鍵,在根據get方法獲取每一個鍵對應的值
* 2,entrySet
*/
public class Test9 {
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("01", "a1");
map.put("02", "a2");
map.put("03", "a3");
// 先獲取map集合的所有鍵的set集合,keyset();
Set<String> keySet = map.keySet();
// 有了Set集合,就可以獲取其迭代
Iterator<String> it = keySet.iterator();
while (it.hasNext()) {
String key = it.next();
// 有了鍵就可以通過map集合的get方法獲取其對應的值
String value = map.get(key);
System.out.println("key" + key + "value:" + value);
}
}
}
entrySet示例
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/*
* Set<Map.Entry<k,v>> entrySet:將map集合中的映射關係存入到了set集合中,
* 而這個關係數據類型就是:Map.Entry
*/
public class Test10 {
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("01", "a1");
map.put("02", "a2");
map.put("03", "a3");
// 將map集合中的映射關係取出,存入set集合中
Set<Map.Entry<String, String>> entrySet = map.entrySet();
Iterator<Map.Entry<String, String>> it = entrySet.iterator();
while (it.hasNext()) {
Map.Entry<String, String> me = it.next();
String key = me.getKey();
String valeu = me.getValue();
}
}
}
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* 練習: 每一個學生都有對應的歸屬地。 學生Student 地址String 學生屬性:姓名,年齡 注意:姓名和年齡相同的視爲同一個學生。
* 保證學生的唯一性。
*
* @author Administrator
*
*/
public class Test5 {
public static void main(String[] args) {
Map<Student1,String> map=new HashMap<Student1,String>();
map.put(new Student1("lisi1",21), "beijign");
map.put(new Student1("lisi2",22), "shanghai");
map.put(new Student1("lisi3",23), "nanjing");
map.put(new Student1("lisi4",24), "wuhan");
//第一種方式取出keySet
Set<Student1> keyset=map.keySet();
Iterator<Student1> it=keyset.iterator();
while(it.hasNext()){
Student1 stu=it.next();
String addr=map.get(stu);
System.out.println(stu+".."+addr);
}
//第二種取出方式:
Set<Map.Entry<Student1, String>> entrySet=map.entrySet();
Iterator<Map.Entry<Student1, String>> iter=entrySet.iterator();
while(iter.hasNext()){
Map.Entry<Student1, String> me=iter.next();
Student1 stu=me.getKey();
String addr=me.getValue();
System.out.println(stu+"..."+addr);
}
}
}
class Student1 implements Comparable<Student1> {
private String name;
private int age;
Student1(String name,int age){
this.name=name;
this.age=age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String toString(){
return name+":"+age;
}
public int hashCode(){
return name.hashCode()+age*34;
}
public boolean euqals(Object obj){//不能加泛型
if(!(obj instanceof Student)){
// return new RuntimeException("類型不匹配");
throw new ClassCastException("類型不匹配");
}
Student1 s=(Student1)obj;
return this.name.equals(s.name)&&this.age==s.age;
}
@Override
public int compareTo(Student1 s) {
// TODO Auto-generated method stub
int num=new Integer(this.age).compareTo(new Integer(s.age));
if(num==0){
return this.name.compareTo(s.name);
}
return num;
}
}
//按照學生姓名比較,自定義比較器。
treeMap
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
/**
* 練習: 每一個學生都有對應的歸屬地。 學生Student 地址String 學生屬性:姓名,年齡 注意:姓名和年齡相同的視爲同一個學生。
* 保證學生的唯一性。
*
* @author Administrator
*
*/
public class Test5 {
public static void main(String[] args) {
// Map<Student1,String> map=new HashMap<Student1,String>();
TreeMap<Student1, String> map = new TreeMap<Student1, String>(
new StuNameComparator());
map.put(new Student1("blisi1", 21), "beijign");
map.put(new Student1("lisi2", 22), "shanghai");
map.put(new Student1("lisi2", 22), "nanjing");
map.put(new Student1("lisi4", 24), "wuhan");
// 第一種方式取出keySet
Set<Student1> keyset = map.keySet();
Iterator<Student1> it = keyset.iterator();
while (it.hasNext()) {
Student1 stu = it.next();
String addr = map.get(stu);
System.out.println(stu + ".." + addr);
}
// 第二種取出方式:
/*
* Set<Map.Entry<Student1, String>> entrySet=map.entrySet();
* Iterator<Map.Entry<Student1, String>> iter=entrySet.iterator();
* while(iter.hasNext()){ Map.Entry<Student1, String> me=iter.next();
* Student1 stu=me.getKey(); String addr=me.getValue();
* System.out.println(stu+"..."+addr); }
*/
}
}
class Student1 implements Comparable<Student1> {
private String name;
private int age;
Student1(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String toString() {
return name + ":" + age;
}
public int hashCode() {
return name.hashCode() + age * 34;
}
public boolean euqals(Object obj) {// 不能加泛型
if (!(obj instanceof Student)) {
// return new RuntimeException("類型不匹配");
throw new ClassCastException("類型不匹配");
}
Student1 s = (Student1) obj;
return this.name.equals(s.name) && this.age == s.age;
}
@Override
public int compareTo(Student1 s) {
// TODO Auto-generated method stub
int num = new Integer(this.age).compareTo(new Integer(s.age));
if (num == 0) {
return this.name.compareTo(s.name);
}
return num;
}
}
class StuNameComparator implements Comparator<Student1> {
@Override
public int compare(Student1 o1, Student1 o2) {
// TODO Auto-generated method stub
int num = o1.getName().compareTo(o2.getName());
if (num == 0) {
return new Integer(o1.getAge()).compareTo(new Integer(o2.getAge()));
}
return num;
}
}
import java.util.TreeMap;
/**
* 第一次用a字母作爲鍵去找集合,那麼集合沒有a這個鍵,所以也沒有對應的次數。 返回null, 如果爲null,就將a字母和1存入集合。
* 如果指定的鍵已經存在,說明有對應的次數,就將對應的次數取出,並自增後再重新存入集合。
*
* @author Administrator 思路: 1,將字符串轉換成字符數組,因爲要對每一個字母進行操作。
* 2,定義一個map集合,因爲打印結果的字母有順序,所以使用treemap集合。
* 3,遍歷字符數組,將每一個字母作爲字母作爲鍵去查map集合,如果返回null,就將該字母和1存入map集合中,
* 如果返回不是null,說明,該字母在map集合中已經存在,並有對應的次數,並獲取該次數,並進行自增。
* 然後將該字母和子增後的次數存入map集合中,覆蓋原來鍵所對應的值 4,將map集合中的數據變成指定的字符串形式返回。
*/
public class Test6 {
public static void main(String[] args) {
String str = "tabdf..daf";
charCount(str);
}
public static String charCount(String str) {
char[] chs = str.toCharArray();
int count = 0;
TreeMap<Character, Integer> tm = new TreeMap<Character, Integer>();
for (int x = 0; x < chs.length; x++) {
if (!(chs[x] >= 'a' && chs[x] <= 'z' || chs[x] >= 'A'
&& chs[x] <= 'Z')) {
continue;
}
Integer value = tm.get(chs[x]);
/*
* if (value == null) { tm.put(chs[x], 1); } else { value = value +
* 1; tm.put(chs[x], value); }
*/
if (value != null) {
count = value;
}
count++;
tm.put(chs[x], count);
count = 0;
}
System.out.println(tm.toString());
return null;
}
}