第十天
權(quán)限修飾符
public? protected? default? private
同一類? true true true true
同一包 true true true false
子父類(不同包) true true flase false
不同包 true false false false
1.修飾類中的成員(方法和變量)
2.修飾類:public:任何地方都可以訪問夺荒,在其他劇中使用需要導(dǎo)包!
default:只有在同一個包中訪問!
權(quán)限修飾符:設(shè)置成員類的訪問范圍涩僻!
創(chuàng)建 Object的對象:
Object是所有類的父類
1.toString():返回對象的地址憔恳,如果想換,就重寫 父類的方法
2.equals():比較兩個對象是否是同一個對象!掩蛤,比較對象的地址哮伟!
第十一天
==:比較的是地址(引用數(shù)據(jù)類型)
equals:比較的是 字符串的值
沒有new對象
字符串保存在字符串常量池(字符串常量區(qū))干花,當(dāng)你需要給一個字符串變量賦值時候妄帘,會先到字符串常量區(qū)中查找,如果沒有就創(chuàng)建一個池凄,在將所存的地址賦值給字符串變量抡驼!如果有就不在創(chuàng)建,直接將地址給變量肿仑。
new對象
字符串也是保存在字符串常量池(常量區(qū))婶恼,當(dāng)你需要給一個字符串變量賦值的時候,先到字符串常量池中查找柏副,如果沒有就在常量池中創(chuàng)建一個 勾邦,將值賦值到堆中的對象 ,如果有就不再創(chuàng)建割择,將值賦值到堆中的對象 眷篇。
截取字符串:String str = new String("字符數(shù)組char",截取的
開始的值荔泳,截取到哪里)
int length()? 獲取字符串的長度
char charAt(int index) 獲取特定位置的字符 (注意角標(biāo)越界)
int indexOf(String str) 獲取特定字符的位置(overload)
int lastIndexOf(int ch) 獲取最后一個字符的位置
類方法運行 String.valueof(轉(zhuǎn)化)將其他的類型轉(zhuǎn)換為字符串
char[] s= 字符串.toCharArray()將字符串轉(zhuǎn)化為字符數(shù)組
s.replace("需要替換的字符"蕉饼,"替換的字符"); 替換字符串,返回的是一個新的字符串
s.split(切割的符號)? 切割字符串玛歌,返回是String數(shù)組
s.substring(截取開始的位置昧港,截取結(jié)束的位置)截取字符串
s.toUpperCase()字符轉(zhuǎn)大寫
s.toLowerCase()字符轉(zhuǎn)小寫
s.trim()去除空格!
第十二天
StringBuffer :字符串緩存區(qū):存在一個字符數(shù)組支子,默認(rèn)會有一個大写捶省:16字符,如果超了就會翻一倍值朋,類似于oc中的 可變數(shù)組
StringBuffer:具有容器的特性:
1.增加叹侄!
StringBuffer str = new StringBuffer();
str.append("字符串");
2.插入昨登!
str.insert(某一位置插入(后一位)趾代,插入的字符串);
3.刪除 !
str.delete(開始刪除的位置(包含起始)丰辣,結(jié)束刪除的位置(不包含結(jié)束))撒强;
deleteCharAt(刪除指定位置的字符串)
4.修改 !
str.replace(開始的位置,結(jié)束的位置笙什,替換的字符串)飘哨;
5.翻轉(zhuǎn)字符串!
str.reverse()得湘;
6.替換指定位置的字符杖玲!
str.setCharAt(指定的位置,替換的字符)淘正;
7.截取字符串摆马!
str.substring(開始的位置)臼闻;
str.substring(開始的位置,結(jié)束的位置)囤采;
8.查找述呐!
str.indexOf(需查找的字符串);查找小的字符串在大的字符串的位置
str.lastIndexOf(字符串)蕉毯;查找最后一個
str.lastIndexOf(字符串乓搬,指定位置);從指定位置開始查找
str.toString()將String變?yōu)镾tring
str.charAt(位置)查找指定的字符
StringBuffer 和 StringBulider 的使用方式是一樣的代虾!
相同點:1.兩個類都是字符緩沖類进肯!
2.兩個類的方法一樣
不同點:1.StringBuffer線程使用更安全,效率低棉磨;StringBulider線程不安全江掩,效率高
2.StringBuffer是jdk1.0就有了,StringBulider1.5才有乘瓤,推薦StringBulider
System的使用:
System是系統(tǒng)類环形,主要用途是用來獲取系統(tǒng)的數(shù)據(jù)? ,無參且不能被實例化衙傀,里面的方法都是靜態(tài)方法抬吟!
1.復(fù)制數(shù)組:arraycopy(需要復(fù)制的數(shù)組對象,復(fù)制的起始位置统抬,復(fù)制到的數(shù)組火本,復(fù)制到數(shù)組的起始位置(后一位!)蓄喇,指定數(shù)據(jù)的長度)发侵;
例:
int[] arr = {1,3,4,7,8,9};
int[] arr1 = new int[20];
arr1[0] =4;
arr1[1] = 5;
arr1[2] = 6;
System.arraycopy(arr,3,arr1,3,3);
2.返回以毫秒為單位的當(dāng)前時間:currentTimeMillis()妆偏;
3.終止jvm:System.exit(0);其實調(diào)用的是Runtime.exit()盅弛;方法G睢!
4.運行垃圾回收器:System.gc()挪鹏;
5.確定當(dāng)前系統(tǒng)的屬性:getProperties()见秽;
例:
Properties priperties = System.getProperties();
priperties.list(System.out)讨盒;
獲取操作系統(tǒng):以鍵:值? ? 存在
System.out.println(priperties.getProperty("os.name"));
在Java中最少有兩個線程:1.主線程 2.垃圾回收線程
Runtime:該程序代表了運行的環(huán)境解取,在程序中是單例
1.getRuntime():返回當(dāng)前程序運行的環(huán)境變量對象。
例:Runtime run = Runtime.getRuntime()返顺;
2.exec():根據(jù)指定的路徑來執(zhí)行對應(yīng)的可執(zhí)行文件禀苦!
例:Process process = run.exec(路徑)蔓肯;
3.destroy():殺掉子進(jìn)程的可執(zhí)行的文件!
例:process.destroy()振乏;
4.exit():退出jvm虛擬機蔗包!
例:run.exit();
5.freeMemory():返回虛擬機的內(nèi)存
例:System.out.println(“虛擬機內(nèi)存還剩:”+run.freeMemory());
maxMemory();試圖使用最大的內(nèi)存
totalMemory()慧邮;獲取總內(nèi)存调限!
日期類的學(xué)習(xí):jdk1.1之前是Date,jdk1.1之后使用的是Calendar類來代替Date
date:獲取系統(tǒng)當(dāng)前的時間误澳,精確到毫秒
獲取當(dāng)前時間:Date date = new Date()耻矮;
1.getDate()返回多少號,棄用
Calendar:是一個抽象的類不能直接創(chuàng)建對象的忆谓!
例:Calendar cl = Calendar.getInstance()裆装;創(chuàng)建一個日歷單例
System.out.println("年"+cl.get(Calender.YEAR));獲取年份
System.out.println("月"+(cl.get(Calender.MONTH)+1));獲取月份陪毡,十二進(jìn)制 0-11
日+ Calender.DATE 獲取日
星期+? ((Calender.DAY_OF_WEEK)-1);獲取星期米母,七進(jìn)制 0-6
時+ Calender.HOUR_OF_DAY;獲取小時
分+ Calender.MINUTE;獲取分鐘
秒+ Calendar.SECOND毡琉;獲取秒
System.out.println(cl.getTimeInMillis());返回1970到現(xiàn)在的毫秒數(shù)
SimpleDateFormat:時間的打印格式
1.將一個時間通過制定的格式以字符串形式輸出
2.將一個字符串也是以指定的格式轉(zhuǎn)為時間類型
例:
Date date = new Date()铁瞒;
指定一格式
String formate = "yyyy年MM月dd日? hh:mm:ss";
創(chuàng)建格式化對象:
SimpleDateFormate dateF = new SimpleDateFormate(formate);
String time = dateF.format(date)桅滋;
打印時間
System.out.println(time)慧耍;
定義字符串時間要與格式化格式一樣
String dateStr = “時間”;
Date newDate = dateF.parse(dateStr)丐谋;
System.out.println(newDate)芍碧;
finalize 是程序或?qū)ο笤诒籫c回收時調(diào)用此方法
第十三天
Math:數(shù)學(xué)類
Math.abs(數(shù)字):返回絕對值
Math.ceil(數(shù)字(duoble))向上取整!
Math.floor(數(shù)字(double)):向下取整
Math.round(數(shù)字):四舍五入
(int)(Math.random()*范圍):產(chǎn)生隨機數(shù)
Random random = new Random(10)号俐;產(chǎn)生0-9的隨機數(shù)
random.nextInt(10)泌豆;同上!
Array:用來存同一種數(shù)據(jù)類型的容器吏饿;
Object【】 arr:可以存放任意類型的對象踪危!
1.但比較浪費內(nèi)存,而且容量是固定的猪落,無法隨元素的變化而變化贞远!
2.存放的數(shù)據(jù)類型不統(tǒng)一
集合:用來存放對象的容器,對象類型是任意的笨忌,長度可變蓝仲!collection!
集合與數(shù)組的區(qū)別:
數(shù)組和集合類都是容器
數(shù)組長度是固定的,集合長度是可變的袱结。數(shù)組中可以存儲基本數(shù)據(jù)類型亮隙,集合只能存儲對象數(shù)組中存儲數(shù)據(jù)類型是單一的,集合中可以存儲任意類型的對象擎勘。
集合類的特點
用于存儲對象咱揍,長度是可變的,可以存儲不同類型的對象棚饵。集合中只能存對象煤裙!
集合的結(jié)構(gòu):
collection 接口 根接口 集合的公共都在接口中! 單列集合
----》List 接口 可以有重復(fù)元素的集合噪漾,有序
List特有的方法: 接口
---->ArrayList:存在一個數(shù)組(Object[]),添加硼砰、刪除元素慢,查找快
元素在內(nèi)存中是有序的欣硼!默認(rèn)的數(shù)組長度是Object[10];當(dāng)不夠時會增加為原來的1.5倍题翰,涉及到了增容和數(shù)組的拷貝所以較慢
ArrayList的特有方法:
ArrayList list = new ArrayList();
ensureCapacity(容量);手動增加容量
trimToSize()诈胜;調(diào)整容量剛好符合元素的個數(shù)
---->LinkedList:添加元素快豹障,刪除、查找慢:鏈?zhǔn)降慕Y(jié)構(gòu)=剐佟血公!
元素在內(nèi)存中是無序的,但打印是有序的
LinkedList的特有方法:
LinkedList list = new LinkedList()缓熟;
list.add(對象)累魔;
list.addFlist(對象);
list.addLast(對象)够滑;
addFlist():添加位于第一個的元素
addLast()垦写;添加位于最后一個的元素
----》Set 接口 不可以有重復(fù)元素的集合,無序
集合的目的:增刪改查更方便彰触!
例:Collection是接口 需要通過實現(xiàn)類來創(chuàng)建對象梯投,集合只能存對象
Collection? coll = new ArrayList();
增加:
1:add()將指定對象存儲到容器中况毅,add 方法的參數(shù)類型是Object便于接收任意對象
coll.add(10(對象))晚伙;添加指定的對象
2:addAll()將指定集合中的元素添加到調(diào)用該方法和集合中
Collection coll1 = new ArrayList<>();
coll1.add("李四");
coll.addAll(coll1)俭茧;將一個數(shù)組中的元素添加到另一個數(shù)組中
刪除:
3:remove()將指定的對象從集合中刪除
coll.remove("李四");從集合中刪除指定的對象
4:removeAll()將指定集合中的元素刪除
coll.removeAll(coll1);刪除指定集合中的元素
修改
5:clear()清空集合中的所有元素
coll.clear();清空集合中的所有元素!
判斷
6:isEmpty()判斷集合是否為空
coll.isEmpty()漓帚;返回boolean值母债,
7:contains()判斷集合何中是否包含指定對象
coll.contains("元素");查找指定元素返回boolean
如果比較的是自定義對象? 這時候需要重寫equals方法和hashCode方法
其實也是調(diào)用可equalse();方法
8:containsAll()判斷集合中是否包含指定集合
其實也是調(diào)用可equalse();方法
c.contatinsAll(conll)毡们;
獲取:? 9:int size()返回集合容器的大小
coll.size()迅皇;返回有多少個!
轉(zhuǎn)成數(shù)組10:toArray()集合轉(zhuǎn)換數(shù)組
Object[] o = c.toArray()衙熔;返回的是數(shù)組登颓!
11.保留集合中相同的對象 retainAll()
c.retainAll(c1);保留兩個集合中共有的對象红氯,求交集
遍歷集合元素框咙!
1.將集合變?yōu)閿?shù)組
Object[] o = c.toArray(可以指定對象開始變數(shù)組);
for(int i=0痢甘;i
System.out.println(o[i])喇嘱;
}
List特有的方法:List中特有的方法都是通過下標(biāo)來操作的!
---->ArrayList
---->LinkList
List list = new List<>();
插入
1.add(對象,指定位置)塞栅;
addAll(指定位置者铜,集合); 插入集合
list.add("張三");
list.add(0,"李四");
集合1.addAll(指定位置放椰,集合2)作烟;
返回、獲取
2.get(指定位置)
System.out.println(list.get(位置));
打印集合中的對象
查找
3.IndexOf()砾医;查找指定的對象在集合中第一個出現(xiàn)的位置:返回位置
System.out.println("是否存在對象:在什么位置:"+list.indexOf("對象"));
4.lastIndexOf()拿撩;查找指定的對象在集合中最后一次出現(xiàn)的位置:返回位置
System.out.println("是否存在對象:在什么位置:"+list.lastIndexOf("對象"));
5.listIterator();迭代器:用于操作集合中的元素藻烤,增刪绷雏,獲取集合中的對象!
使用的注意事項:
1.當(dāng)用迭代器來操作集合元素時怖亭,不要集合來操作元素涎显!java.util.ConcurrentModificationException:不允許在用迭代器時用集合
2.
Iterator:迭代器的超級接口:所有的迭代器都繼承于Iterator
迭代器默認(rèn)指向第一個元素(指針);當(dāng)調(diào)用next()方法后指針就會下移一位兴猩,不再指向第一個期吓!
迭代器中常用的方法:
例:Collection c = new ArrayList<>();
c.add("狗娃");..... 添加元素
Iterator it = c.iterator();
1.hasNext()倾芝;判斷當(dāng)前指針是否存在元素讨勤,返回boolean
System.out.println("當(dāng)前指針是否存在元素?"+it.hasNext())晨另;
2.next()潭千;獲取當(dāng)前指針指向的元素,當(dāng)被調(diào)用是就會下移
while(it.hasNext()){
System.out.println(it.next());
}
3.remove()借尿;移除最后一次操作的元素
it.remove()
ListItreaor:特有的方法
例:List list = new List()刨晴;
list.add(“”)屉来;.....
1.獲取迭代器對象
ListIterator it = list.listIterator();
2.hasPrevious()狈癞;判斷當(dāng)前指針上一個是否存在元素
it.hasPrevious()茄靠;獲取當(dāng)前指針指向的上一個元素,返回boolean
3.previous()蝶桶;獲取上一個值慨绳,指針有上移了一位
it.previous();
倒序遍歷集合中的元素
1.首先需要指針移動到最后一個元素的下方
while(it.hasNext()){
it.next();
}
while(it.hasPrevious()){
System.out.println(it.prevopis())真竖;
}
4.previousIndex()脐雪;返回上一個指針的索引值
System.out.println(it.previousIndex());
5.add()疼邀;通過迭代器的指針的位置來添加元素喂江,添加到當(dāng)前的指針
it.add(“對象”);
6.set()旁振;替換元素
it.set(對象)获询;,替換當(dāng)前指針指向的元素拐袜,最好不要與add()一起用吉嚣,當(dāng)用時需要it.next(),否則指針會不知道指哪里
更新
6.set(指定位置蹬铺,替換的對象)尝哆;更換指定位置的對象
list.set(位置,對象)甜攀;
刪除
7.remove(指定位置)秋泄;刪除指定索引位置!
list.remove(list.size()-1)规阀;
8.List.subList(開始恒序,結(jié)束);截取集合的某一段谁撼,生成一個新的集合
List.subList(開始歧胁,結(jié)束)將指定的位置保留為另外一個集合。
List newList = list.subList(開始的位置,結(jié)束的位置)厉碟;
遍歷集合
for(int i = 0喊巍;i
System.out.println(list.get(i));
}
第十四天
當(dāng)想讓對象打印成員變量時可復(fù)寫toString()方法!
1.LinkedList:
LinkedList list = new LinkedList()箍鼓;
list.add()崭参;.....
list.addFirst(“對象”);添加第一個
list.addLast()款咖;添加最后一個
list.getFirst()阵翎;輸入第一個逢并;
list.getLast();輸出最后一個
list.removeLast()郭卫;刪除最后一個,返回 最后一個元素
list.removerFirst()背稼;刪除第一個贰军,返回 最后一個元素
當(dāng)集合中沒有元素時會拋出java.util.NosuchElementException這個異常
2.數(shù)據(jù)節(jié)構(gòu)
1.棧:先進(jìn)后出
push();當(dāng)被推入時會被推入到第一的位置蟹肘!在棧中
list.push(對象)词疼;往集合中的堆棧中推入一個對象
pop();當(dāng)推出時會移除最上一位的對象帘腹!在棧中
當(dāng)push()的被去除完后就會變成ArrayList的順序來----》小的先走贰盗,大的后走
list.pop();在集合中的堆棧中推出一個對象
2.隊列:先進(jìn)先出
offer()阳欲;按順序推入到集合中
list.offer()舵盈;添加到最后一個!
poll()球化;推出ArrayList的第一個
list.poll()秽晚;推出第一個
3.獲取逆序的迭代器:descendingIterator
Iterator it = list.descendingIerator();返回的迭代器時逆序的狀態(tài)!
while(it.hasNext()){
System.out.println(it.next())筒愚;
}
Vector: 描述的是一個線程安全的ArrayList 使用跟ArrayList一樣
Vector與ArrayList的區(qū)別:
相同點:底層都是使用Object[]數(shù)組來實現(xiàn)
不同點:1.ArrayList是線程不同步赴蝇,操作效率高!
Vector是線程同步的巢掺,操作效率低
2.ArrayList是在jdk1.2出現(xiàn)的句伶,Vector是在jdk1.0出現(xiàn)的!
Set集合:也是接口陆淀,繼承與Collection接口
特點:無序的元素不能重復(fù)
---->HashSet():
存值原理:存在于哈希表中考余,會通過調(diào)用對象的hashCode(先)和equals(后)方法獲取哈希值,然后用移位的運算倔约,獲取哈希表的位置值秃殉!
情況一:如果我計算的位置上沒有任何元素,將對象放在位置上
情況二:如果計算的位置上已經(jīng)存在對象浸剩,這時候就會將要存的對象與已存在的對象作比較钾军,如果equals返回的是true :對象就是重復(fù)元素,如果是false就在原來的位置上添加绢要!
哈希表中是以桶式的結(jié)構(gòu)來存放數(shù)據(jù)吏恭,一格可存放多個對象!
例:復(fù)寫HashCode(){
如果是string就返回this.成員變量.hashCode()值(成員變量V刈铩)
int就返回this.成員變量
return 自定義的哈希樱哼;
}
復(fù)寫equals(){
如果是string就返回(this.對比值).equals(obj.成員變量)
int就返回this.成員變量==obj.成員變量
return 自定義的值是否相等
}
例:
Set set = new HashSet()哀九;
set.add(對象)掠拳;.....當(dāng)添加的元素重復(fù)時無法進(jìn)行添加铃慷!返回Boolean值
打印的是無序的!躬存!
遍歷Hashset()集合
1.集合變?yōu)閿?shù)組遍歷
2.迭代器遍歷(無序:添加的順序和打印出來的順序是不一樣的)
---->TreeSet()茄唐;使用元素的自然順序?qū)υ剡M(jìn)行排序.底層使用二叉樹實現(xiàn)
注意點:存進(jìn)去的對象需要具備自然排序的特性息裸,取第一個字符根據(jù)阿斯特碼(ASCII)來排!
1.往TreeSet添加對象的時候沪编,如果對象有自然排序的特性呼盆,就按照這個自然排序進(jìn)行排序!
2.往TreeSet添加對象時蚁廓,如果對象本身不具備自然排序的特性访圃,運行直接報錯,如果要儲存對象相嵌,那么對象的類必須要實現(xiàn)一個Comparable ? 接口的compareTo方法腿时!
public int compareTo(Object o){
Book b =(Book)o;
return this.對比成員-b.對比的成員;
}
3.往TreeSet添加對象時平绩,如果對象本身不具備自然排序的特性圈匆,并且沒有實現(xiàn)Comparable? 接口,那么這個時候就需要創(chuàng)建一個TreeSet類的時候傳入一個比較器捏雌。
比較器的定義方式
TreeSet set = new TreeSet(new sunComp(創(chuàng)建比較器))跃赚;在main或別的類的時候
比較的類(比較器也是一個類)必須與Compartor相接
class sunComp(類名)implements Compartor{
復(fù)寫此方法!
public int compare (Object o1,Object o2){
o1,o2集合中的對象:book
Book b1= (Book)o1;
Book b2 = (Book)o2;
return? b1.對比的值-b2.對比的值性湿;
}
}
4.如果類中實現(xiàn)了Comparable的接口纬傲,又創(chuàng)建TreeSet時傳入了一個比較器,這時候以比較器為標(biāo)準(zhǔn)
例:
TreeSet set = new TreeSet()肤频;
set.add("對象")叹括;
會自動的將對象排序!
字符串的比較規(guī)則:
1.獲取字符串的第一個值進(jìn)行比較宵荒,通過自然排序比較汁雷,如果都是一樣的就比較下一個值還是一樣的就再比較下一個,直到無法再比較
2.這個時候就會比較字符串的長度报咳!
第十五天
二叉樹:紅黑樹規(guī)則:左小右大侠讯!
泛型:確定集合中只能存放某一種數(shù)據(jù)類型的對象,jdk1.5之后推出的
優(yōu)點:1.將運行時的錯誤提前到編譯時暑刃。2.避免了無謂的強制轉(zhuǎn)換厢漩!
如果傳進(jìn)去的是基本數(shù)據(jù)類型,接收時應(yīng)用改用它的包裝類來接收岩臣!
int--->Integer;
short--->Short;
double--->Double;
float--->Float;
byte--->Btey;
boolean--->Boolean;
long--->Long;
char--->Charactor
ArrayList<這個就是泛型> = new ArrayList<這個也是>();
自定義泛型方法:就是一個數(shù)據(jù)類型的 占位或一個數(shù)據(jù)類型變量溜嗜,一般用T(Typt)或E(Element)來做占位符,占位符可以隨意寫宵膨,必須要滿足遵守標(biāo)識符的命名規(guī)范!
注意:1.泛型方法中自定義一個泛型數(shù)據(jù)類型實在實際參數(shù)傳遞時被確定的
2.泛型所用標(biāo)識符需要符合標(biāo)識符的命名規(guī)范炸宵!一般用大寫辟躏!
格式:public static T 方法名(T s){
return s;
}
接收:String s = 方法名("傳進(jìn)去的對象");
定義一個泛型類:
定義格式:
class 類名<聲明自定義的泛型>{}
泛型類的使用注意點:
1.泛型類定義的自定義泛型的類型是在創(chuàng)建泛型類對象時確定的!
2.如果一個自定義泛型類在創(chuàng)建時候沒有指定類型焙压,默認(rèn)為Object類型鸿脓!
3.靜態(tài)方法是不能夠使用自定義類的泛型,只能在靜態(tài)方法中再次寫一個泛型涯曲!
泛型接口的定義方式
interface 接口名<聲明自定義的泛型>{}
class 類名 implements 接口名<指定類型>{}
泛型接口注意點:
1.接口上自定義的泛型是在實現(xiàn)接口時被指定的!
2.如果接口上沒有指定接口在塔,默認(rèn)為Object類型幻件!
3.如果需要創(chuàng)建接口實現(xiàn)類對象是指定數(shù)據(jù)類型,
那么需要格式:class 類名 <聲明自定義泛型> implements? 接口<聲明自定義泛型>{}
Java可以后臺數(shù)據(jù)管理也可以前端;桌!绰沥!
Map:集合? 接口? 雙列集合? K:V? 鍵值對? OC中的字典很象!
特點:存儲數(shù)據(jù)是以鍵和值的方式贺待,鍵不允許重復(fù)徽曲,值是允許重復(fù)的!
----->HashMap:基于哈希表麸塞,而且是無序的秃臣!
使用注意點:
1.鍵可以是任意的對象!哪工,值也可以是任意的對象奥此!
2.Map集合中也可以存集合(嵌套集合)(List、Map)雁比;
3.當(dāng)鍵相同時后面的Value會覆蓋前面的Value
儲存原理:也是使用哈希表來存放稚虎!
往HashMap添加元素,首先會調(diào)用鍵的HashCode()方法? 獲得一個哈希值偎捎,然后經(jīng)過運算獲取一個位置:情況有:
1.如果位置沒有元素蠢终,就直接將元素存放在該位置
2.如果位置上有元素,就會調(diào)用元素的equals()方法與這個位置上的元素做比較茴她,如果返回是true那么就被視為相同的鍵 就不存了寻拂;false就是不同的鍵 就存該元素
----->TreeMap:二叉樹的結(jié)構(gòu)儲存。特點:以鍵來做自然排序的特性败京!
使用注意點:
1.往TreeMap添加的元素時兜喻,如果元素的鍵具備自然排序,那么就會通過自然排序?qū)υ剡M(jìn)行排序赡麦!
2.如果不具備自然排序特性朴皆,鍵所屬的類必須實現(xiàn)Comparable 接口帕识,把鍵的比較規(guī)則定義在compareTo()方法中!
3.如果不具備自然排序特性遂铡,也沒有實現(xiàn)Comparable接口肮疗,創(chuàng)建TreeMap的時候給其一個比較器
結(jié)構(gòu):
class 類名 implements Compartor 接口{
如果返回的是負(fù)數(shù)就是在后面
是1就是在前面
0就是不添加!
}
鍵的比較規(guī)則定義在compare方法扒接!
----->HashTable:HashMap一樣的使用伪货,線程安全,訪問比較慢(了解<卣)
Map常用方法:
Map map = new HashMap()碱呼;
添加:
put(K,V)宗侦;
map.put(鍵(可存對象)愚臀,值(可存對象));
putAll(K矾利,V(集合))姑裂;A.putAll(B);將B中的元素添加到A中
Map map2 = new HashMap();
map.putAll(map2)男旗;
刪除:
clear()舶斧;
map.clear();清空Map集合中所以的元素察皇!
remove()茴厉;
map.remove(鍵);通過鍵刪除指定的元素让网!
獲妊接恰:
get(鍵);
map.get(鍵)溃睹;通過鍵來獲取值而账!
size();
map.size()因篇;返回map集合里面的元素個數(shù)泞辐!
獲取鍵的方法
判斷:
isEmpty();判斷集合是否為空竞滓!
map.isEmpty()咐吼;判斷集合中是否為空!false是不為空商佑!
containsKey(K)锯茄;
map.containsKey(鍵);判斷是否存在某一個鍵!有返回true
containsValue(V)肌幽;
map.containsValue(值)晚碾;判斷是否含有某一個值!需要復(fù)寫equals()和HashCode()方法喂急!
Map的遍歷方式:
迭代器遍歷:
entrySet()格嘁;
KeySet();
values()廊移;
例:
1.定義Map
Map map = new HashMap();
2.添加元素
map.put("范冰冰","李晨");
3.遍歷
map遍歷元素方式一:keySet()糕簿;獲取所有的鍵用Set集合來保存!
特點:通過遍歷鍵狡孔,通過鍵來取值
Set set = map.keySet();
Iterator it = set.iterator();
while(it.hashNext()){
String key = it.next();
System.out.println("鍵"+key+“:值”+map.get(key))懂诗;
}
map遍歷元素方式二:values():獲取map集合中所有的值,用Collection集合保存
Collection coll = map.values();
Iterator it = coll.iterator();
while(it.hashNext()){
String value = it.next();
System.out.println(“值:”+value)苗膝;
}
map遍歷元素方式三:entrySet()
Set> entry = map.entrySet();
Iterator> it = entry.iterator();
while(it.hashNext()){
Map.Entry entry = it.next();
Map.Entry:接口:提供給用戶操作map集合
getKey()响禽;獲取鍵
getValue();獲取值
setValue()荚醒;更改值
System.out.println("鍵:"+entry.getKey()+"值:"+entry.getValue());
}
Collection:接口
Collections:集合的工具類
Collection與Collections的區(qū)別隆嗅?
Collection 是一個單列集合的根接口界阁,Collections是操作集合的工具類!只能操作list集合 胖喳!
Collections中常有的方法
Collections:常見方法:
Collections.sort()泡躯;排序
1, 對list進(jìn)行二分查找:
前提該集合一定要有序丽焊。
int binarySearch(list,key)较剃;
Collections.binarySearch(集合,"對象");返回索引的位置? 沒找到返回是一個負(fù)數(shù)技健,索引
//必須根據(jù)元素自然順序?qū)α斜磉M(jìn)行升級排序
//要求list 集合中的元素都是Comparable 的子類写穴。
int binarySearch(list,key,Comparator);
2,對list集合進(jìn)行排序雌贱。
sort(list);
//對list進(jìn)行排序,其實使用的事list容器中的對象的compareTo方法
sort(list,comaprator);
//按照指定比較器進(jìn)行排序
3啊送,對集合取最大值或者最小值。
max(Collection)
max(Collection,comparator)
min(Collection)
min(Collection,comparator)
4欣孤,對list集合進(jìn)行反轉(zhuǎn)馋没。
reverse(list);
5,對比較方式進(jìn)行強行逆轉(zhuǎn)降传。
Comparator reverseOrder();
Comparator reverseOrder(Comparator);
6篷朵,對list集合中的元素進(jìn)行位置的置換。
swap(list,x,y);
7,對list集合進(jìn)行元素的替換声旺。如果被替換的元素不存在笔链,那么原集合不變。
replaceAll(list,old,new);
8艾少,可以將不同步的集合變成同步的集合卡乾。
Set synchronizedSet(Set s)
Map synchronizedMap(Map m)
List synchronizedList(List list)
9.如果想要將集合變數(shù)組:
可以使用Collection 中的toArray 方法。注意:是Collection不是Collections工具類
傳入指定的類型數(shù)組即可缚够,該數(shù)組的長度最好為集合的size幔妨。
第十六天
進(jìn)程:就是正在運行的程序,作用是分配內(nèi)存讓應(yīng)用程序能夠運行谍椅!
windows系統(tǒng)號稱多任務(wù)(可以同時運行多個應(yīng)用程序)误堡。
宏觀上:windows確實是運行的多個程序
微觀上:CPU快速作了切換操作,肉眼不可察
線程:線程在一個進(jìn)程中負(fù)責(zé)代碼的執(zhí)行雏吭!就是一個進(jìn)程的執(zhí)行路徑锁施!
Java程序在運行的時候,jvm會幫我們創(chuàng)建一個主線程和一個垃圾回收器(也是一個線程)杖们。主線程主要負(fù)責(zé)main方法中的代碼執(zhí)行悉抵。垃圾回收器負(fù)責(zé)垃圾回收!main是主線程摘完!
一個Java程序中至少有兩個線程姥饰。
多線程:在一個進(jìn)程中有多個線程存在并且線程“同時”執(zhí)行不同的任務(wù)⌒⒅危“同時”:單核CPU快速切換多個線程執(zhí)行任務(wù)列粪,速度很快,肉眼不可察
好處:1.可以解決一個進(jìn)程中同時執(zhí)行多個任務(wù)的問題
2.可以提高資源的利用率
壞處:1.增加CPU的負(fù)擔(dān)谈飒!不是線程越多越好
2.降低進(jìn)程中線程的執(zhí)行效率岂座。
3.會引發(fā)線程安全問題
4.容易出現(xiàn)死鎖
Java創(chuàng)建線程:
方式一:Thread(線程類)
1.需要定義一個類來繼承Thread類
2.重寫Thread類中的run方法!把自定義線程的任務(wù)代碼寫在run方法中杭措。每一個線程都有自己的任務(wù)代碼费什,jvm創(chuàng)建主線程的任務(wù)代碼就是main,自定義想成的任務(wù)代碼就寫在run方法中瓤介!
class 類名 extends Thread{
public void run(){
//自定義線程的任務(wù)代碼
for(int i=0吕喘;i<100;i++){
System.out.println(“多線程”+i);
}
}
}
3.創(chuàng)建Thread的子類,并且調(diào)用start開啟線程刑桑!
在main中開啟線程氯质,
注:1.在main中代碼的執(zhí)行是從上到下,必須放在執(zhí)行main的上面
2.一旦線程開啟祠斧,就會默認(rèn)執(zhí)行線程對象的run方法闻察,但是直接千萬不要調(diào)用,如果直接調(diào)用run方法就跟普通方法沒有區(qū)別!
類名 名字 = new 類名()辕漂;
名字.start()呢灶;
for(int i=0;i<100;i++){
System.out.println(“主線程”+i)钉嘹;
}
方式二:推薦!由于Java是單繼承鸯乃,所以就不能繼承Thread和該繼承的類,但接口可以有多個跋涣!
1.自定義一個類實現(xiàn)Runable接口缨睡,接口就會提供一個run方法!
2.實現(xiàn)Runable接口中的run方法陈辱。將線程中的任務(wù)寫在run方法中
3.實現(xiàn)Runable接口的實現(xiàn)類對象奖年!
4.創(chuàng)建一個Thread對象
5.調(diào)用Thread的對象的start方法!
class 類名 implements Runnable{
public void run(){
}
}
main函數(shù):
類名 對象名 = new 類名()沛贪;-----》不是線程對象陋守!只有是Thread或者是Thread的子類才是線程對象!
Thread thread = new Thread(對象名)利赋;
thread.start()水评;
為什么要將Runable接口實現(xiàn)類的對象作為參數(shù)傳遞?
讓對象中的run方法能夠在線程中的run方法中執(zhí)行媚送!
線程的生命周期:-
---->CPU的等待資格
---->CPU的執(zhí)行權(quán)
1.創(chuàng)建一個線程:new 子線程類
2.等待運行狀態(tài)之碗,改狀態(tài)只有CPU的等待資格:
3.運行狀態(tài),改狀態(tài)具備了CPU的執(zhí)行權(quán)與CPU的等待資格
4.線程結(jié)束季希,
線程的阻塞狀態(tài):可由運行狀態(tài)轉(zhuǎn)化,一個線程執(zhí)行了sleep或者wait方法幽纷,線程會處于阻塞狀態(tài)式塌!如果是sleep方法,如果超過了睡眠時間線程會立馬進(jìn)入等待運行狀態(tài)友浸!如果是wait峰尝,就需要通過其他的線程來喚醒!
線程中常用的方法:
1.Thread(String name)初始化線程名字
main 函數(shù)中
類名 對象名 = new 類名(“線程名”)收恢;
對象名.setName(“更換線程名”)武学;
Thread maint = Thread.currentThread();CPU當(dāng)前執(zhí)行的線程
System.out.println("獲取線程的優(yōu)先級"+maint.getPriority())伦意;
定義一個構(gòu)造方法來調(diào)用父類的構(gòu)造方法
public 類名(String name){
super(name)火窒;
}
類中重寫run方法
public void run(){
執(zhí)行的代碼!睡眠后打印線程名驮肉!
try{異常只能處理:Thread父類的sleep方法沒有拋出異常所以子類也不允許拋
this.sleep(毫秒)熏矿;或Thread.sleep(“毫秒”);可以拋異常
}catch(異常){
。。票编。褪储。
}
System.out.println(“線程名”+this.getName());
}
2.getName()返回線程的名字
3.setName(String name)設(shè)置線程對象名
4.sleep(毫秒)線程睡眠是靜態(tài)的可以通過類方法調(diào)用!誰執(zhí)行的Thread.sleep就睡眠誰
5.getPriority()返回線程對象的優(yōu)先級默認(rèn)是5慧域,最高是10
6.Thread.currentThread()鲤竹;
CPU當(dāng)前執(zhí)行的線程,指的是正在執(zhí)行的run方法的線程對象
this不是線程對象昔榴!
7.setPriority(10);給該對象設(shè)置線程的優(yōu)先級
線程安全問題:
Java的線程鎖:
方式一:同步代碼塊P猎濉!推薦
Java中的任意一個對象都會有一個對象的狀態(tài)论泛,就可以通過對象的狀態(tài)作為鎖的標(biāo)識符
優(yōu)點:1.同步代碼塊的鎖對象可以由自己指定揩尸,同步函數(shù)是固定的的
2.同步代碼塊可以控制被同步的范圍,同步函數(shù)必須是整個函數(shù)屁奏!
注意:1.任意對象都可以做鎖對象
2.如果在同步代碼塊中調(diào)用sleep方法岩榆,鎖對象不會被釋放!
3.只有真正存在線程安全的時候才會需要使用同步代碼塊坟瓢,否則會降低效率
4.多線程操作鎖對象必須是唯一的勇边,否則無效
static Object? o = new Object(); 鎖的對象應(yīng)該是同一個對象static 或 單例
synchronized(鎖對象 o){鎖對象可以使任意Java中的對象折联,也可以是字符串
代碼A0!诚镰!
}
方式二:同步函數(shù)奕坟,用關(guān)鍵字sybnchronized修飾函數(shù)
同步函數(shù)是否有鎖對象:有!
同步函數(shù)使用注意點:
1.如果是一個非靜態(tài)的函數(shù)清笨,同步函數(shù)的鎖就是調(diào)用方法的對象(this對象)月杉,如果是一個靜態(tài)函數(shù)同步函數(shù)的鎖對象是當(dāng)前函數(shù)所屬類的字節(jié)碼文件(Class對象)!
2.同步函數(shù)的鎖對象固定抠艾,不能夠自己來指定
3.同步函數(shù)是同步整個函數(shù)的代碼塊苛萎!
線程什么時候安全什么時候不安全?
出現(xiàn)線程安全的根本原因:
1.存在兩個或兩個以上的線程检号,并且線程之間共享著一個資源
2.多個語句同時操作的共享資源腌歉!
代碼同步是可以解決線程安全問題!如果使用不當(dāng)會導(dǎo)致線程的死鎖齐苛!
A線程等B線程 翘盖,B線程又在等A線程 結(jié)果兩個人就一直等下去,這時候就造成了線程的死鎖
線程死鎖不一定會出現(xiàn)凹蜂,有可能出現(xiàn)最仑!
死鎖的解決方法:盡量避免出現(xiàn)線程之間的等待問題藐俺!
public void run() {
if("張三".equals(Thread.currentThread().getName())){
synchronized ("遙控器") { //鎖對象就鎖住了
System.out.println("張三拿到了遙控器 ,準(zhǔn)備去拿電池");
synchronized ("電池") {//已經(jīng)被鎖住了
System.out.println("張三拿到了遙控器和電池泥彤,開著空調(diào)欲芹,在也 不冷了");
}
}
}else if("老王".equals(Thread.currentThread().getName())){
synchronized ("電池") { //鎖也被鎖住了? 電池對象的狀態(tài) 變?yōu)殒i住的狀態(tài)
System.out.println("老王拿到電池吟吝,準(zhǔn)備去拿遙控器");
synchronized ("遙控器") { //遙控器也被鎖住了
System.out.println("老王拿到了遙控器和電池菱父,開著空調(diào),在也 不冷了");
}
}
}
}
線程的通訊:一個線程完成自己的任務(wù)剑逃,去通知另外一個線程去完成另外一個任務(wù)浙宜!
wait();等待如果線程執(zhí)行了wait()方法蛹磺,那么該線程就會處于等待狀態(tài)粟瞬,等待狀態(tài)的線程必須通過其他線程來調(diào)用notify()方法來喚醒!通過鎖對象來調(diào)用
try{
鎖對象.wait()萤捆;
}catch(){
}
notify()裙品;喚醒? 隨機喚醒一個
鎖對象.notify();
notifyAll()俗或;喚醒全部線程
生產(chǎn)者和消費者
注意:1.wait和notify都是屬于Object對象的
2.wait方法和notify方法必須在同步線程中使用
3.wait方法和notify方法必須由鎖對象來調(diào)用市怎!
線程的停止:
1.停止一個線程 一般通過一個變量來控制
2.如果需要停止一個處于等待狀態(tài)的線程,應(yīng)配合interrupt方法辛慰!
Thread.currentThread().stop()区匠;停止當(dāng)前前程!已過時帅腌!此方法不安全
對象.interrupt()驰弄;直接調(diào)用interrupt是沒有用的
如何創(chuàng)建后臺(守護(hù))線程:在一個進(jìn)程中只剩下后臺(守護(hù))線程,守護(hù)線程也會死掉速客!
線程默認(rèn)的不是后臺線程揩懒!將某個對象的線程標(biāo)記為守護(hù)線程
對象.setDaemon(布爾值);true是守護(hù) false一般線程
join方法 加入:可以在一個線程中挽封,加入另外一個線程執(zhí)行,前面的線程會等待加入的線程執(zhí)行完畢后在執(zhí)行臣镣!
run方法中加入另外一個線程
類名 對象名 = new 類名()辅愿;
對象.start();
try{如果有一個線程執(zhí)行join語句忆某,有一個新的線程加入点待,在執(zhí)行的線程需要讓步新的線程執(zhí)行完畢,然后才能執(zhí)行
對象.joun()弃舒;
}catch(){
}