Java基礎(chǔ)系列之?dāng)?shù)據(jù)結(jié)構(gòu)和運算

導(dǎo)語

初遇Java之后单雾,我們對Java的歷史行剂、特征以及垃圾回收機制有了初步認識骄恶,接下來我們需要了解下數(shù)據(jù)結(jié)構(gòu)和運算锨用。程序是什么?就是幫人類干事情的工具(程序員就是開發(fā)這個工具的人!)。程序的組成是什么呢剩岳?我的理解是數(shù)據(jù)結(jié)構(gòu)和算法喘帚,這里我們不談算法那么高大上的東西只談基本運算畅姊,畢竟單講算法就能出一本很厚很厚的書了。

數(shù)據(jù)結(jié)構(gòu)


前面我們說到吹由,Java是一門面向?qū)ο蟮恼Z言若未。有人說過這么一句話,“萬物皆對象”倾鲫,其實這也不絕對粗合。Java有8種基本數(shù)據(jù)類型便不算對象,我們先說說這八種基本數(shù)據(jù)類型吧乌昔。

  • 整型
    • byte 在內(nèi)存中占8位隙疚,取值-128 ~127 即 (-2^7) ~ (2^7-1)
    • short 在內(nèi)存中占16位,取值 -32768~32767 即(-2^{15})~ (2^{15}-1)
    • int 在內(nèi)存中占32位磕道,取值(-2^{31})~ (2^{31}-1)
    • long 在內(nèi)存中占64位供屉,取值(-2^{63})~ (2^{63}-1)
  • 浮點型
    • float 32位單精度浮點數(shù),最多存儲4個字節(jié)
    • double 64位雙精度浮點數(shù)溺蕉,最多存儲8個字節(jié)
  • 字符型 char
  • 布爾型 boolean 取值true,false
    說完基本數(shù)據(jù)類型伶丐,我們再談?wù)勔粋€新概念,直接量疯特。直接量通常有三種類型:基本類型哗魂、字符串類型、null漓雅÷急穑基本類型我們剛才已經(jīng)說過了就是上面的八位,那么字符串類型呢邻吞?就是java.lang.String這個類的類型组题,這是個特殊的類,用來存儲字符串抱冷。
    String類型的特點:字符串直接量不能賦值給其他類型如int,long崔列。這和null類型恰恰相反,null類型可以直接復(fù)制任何引用類型和其他基本類型(除了boolean類型)徘层。關(guān)于String字符串還有一點需要指出峻呕,當(dāng)程序第一次使用時利职,JVM會使用常量池來維護這個直接量趣效。當(dāng)再次使用的時候,Java會直接取常量池中的字符串猪贪。
  • 引用數(shù)據(jù)類型 Date date = new Date(),其中date就是個引用數(shù)據(jù)類型跷敬,這個會在后續(xù)的面向?qū)ο笳鹿?jié)進行詳細介紹。

運算


什么是運算热押?小學(xué)生都知道的加西傀、減斤寇、乘、除拥褂?沒錯娘锁!就是這些,然而饺鹃,程序執(zhí)行加莫秆、減、乘悔详、除卻是一件很費勁的事情镊屎,這就引出了我們的位運算。
我們知道茄螃,計算機數(shù)字系統(tǒng)是由0和1組成的缝驳,即二進制。非0即1归苍,逢2進1用狱,因此處理位運算效率會更高。
目前Java支持的位運算有7個霜医,它們分別是:與齿拂、或、非肴敛、異或署海、左移、右移医男、無符號右移砸狞。

  1. 按位與(&)
    System.out.print(5 & 9),我的得到的結(jié)果是1.具體運算如下
    \frac{0101}{1001}=0001
    運算規(guī)則是同1為1,非1為0
    這里有一個經(jīng)典算法~求一個整數(shù)的奇偶:
//我們知道镀梭,偶數(shù)是能被2整除刀森,那么它的二進制表示最后一位一定是0
//根據(jù)與運算,同1為1报账,非1為0研底,那么一個一個二進制數(shù)和1進行與運算就能獲得最后一位值了
int i;
return (i & 1)==0;//偶數(shù)
  1. 按位或(|)
    System.out.print(5 | 9) 運算結(jié)果是13透罢,具體運算如下
    \frac{0101}{1001}=1101
    運算規(guī)則:有1為1榜晦,無1為0
  2. 非(~)
    System.out.print(~5) 運算結(jié)果是:-6
5的原碼:0000 0101
~5 就是:1111 1010
由于這是一個負數(shù),這顯示的是它的補碼羽圃,我們先求得它的反碼乾胶,即補碼-1那就是:
1111 1001
然后翻轉(zhuǎn)過來,高位取1即:
1000 0110
得到結(jié)果是-6

這里有幾個概念:原碼、反碼识窿、補碼斩郎。
正數(shù)的原碼、補碼喻频、反碼相同
負數(shù)的反碼是其的絕對值按位求反
負數(shù)的補碼等于其反碼的尾數(shù)加1

  1. 按位異或(^)
    System.out.print(5 ^ 9) 運算結(jié)果是12缩宜,具體運算如下
    \frac{0101}{1001}=1100
    運算規(guī)則:同假異真,就是說相同為0甥温,不同為1
  2. 左移(<<)
    System.out.print(4<<1) 運算結(jié)果是8脓恕,運算如下
4: 0100
8: 1000 (0100左移一位后得到01000,舍棄高位的0即1000) 
  1. 右移(>>)
    System.out.print(4>>1)運算結(jié)果是2
4: 0100
2: 0010 (0100右移一位后得到0010窿侈,舍棄高位的0即10) 
  1. 無符號右移(>>>)
    System.out.print(-5>>>2)結(jié)果是1073741822
-5的原碼: 1000 0101
-5的補碼: 1111 1011 
無符號右移后:0011...1111 1110(中間省略掉20個1)
這個應(yīng)該是2的30次方減去2就是我們的運算結(jié)果

這個計算的原因是-5默認為int類型32位炼幔,有興趣可以試試-5L(long類型)無符號右移2,會得到一個更大的值史简。

這些運算是計算機底層的運算乃秀,比如說程序5*2,我們寫成5<<1效率會更高些圆兵。
除了位運算跺讯,我們比較常用的還有如=(賦值)運算,比較運算(>,<,==,!=),邏輯運算(&&殉农,|刀脏,!超凳,^),三目運算(? :)等愈污。

Java也提供了加減乘除的算術(shù)運算,但是需要注意的是對于double和float浮點型運算時可能會失去精度轮傍,如1.2+1.9,得到的結(jié)果是3.0999999999999996,不必驚訝暂雹,不止Java,我們在谷歌的console中執(zhí)行(JavaScript),也是得到了這個結(jié)果创夜。很多中語言都存在這個問題杭跪。為了更為精確的計算,Java提供了一個java.math包驰吓,專門作為算術(shù)計算的涧尿。上面這個我們換成BigDecimal.valueOf(1.2).add(BigDecimal.valueOf(1.9))就沒有這個問題了。需要注意的是檬贰,這里不要使用BigDecimal的double類型構(gòu)造器創(chuàng)建對象姑廉,否則還是會出現(xiàn)精度問題

再談String


String對象可謂是面試官的寵兒,各種題目層出不窮偎蘸,我們這里談?wù)凷tring對象庄蹋。首先我們看下String對象在jdk源碼的樣子


image.png

由于篇幅有限,我們的圖上只能看到類的修飾信息迷雪,看不到Java開發(fā)人員寫的注釋限书,我這里可以把一些關(guān)鍵信息貼出來下。

The  class represents character strings. 
All string literals in Java programs, such as  "abc", are
 implemented as instances of this class.
Strings are constant; their values cannot be changed after they
are created. String buffers support mutable strings.
Because String objects are immutable they can be shared.

不難看出章咧,String是一個字符串對象倦西,代表所有的字符串實例,創(chuàng)建后不能修改赁严,所以可以共享扰柠。上面我們也說過,String對象賦值后疼约,JVM會將該字符串緩存到常量池中卤档,當(dāng)下次使用的時候,直接從常量池獲取程剥。

String a = "helloworld";
String b = "hello"+"world";
String c = new String("helloworld");

這里面a==b劝枣,但是a!=c(這個比較容易理解织鲸,a為字符串直接量舔腾,c為字符串對象的地址)。我們將以上代碼編譯搂擦,打開class文件稳诚,發(fā)現(xiàn)結(jié)果是

image.png

我們可以這樣理解,當(dāng)編譯器能確定字符串的時候瀑踢,系統(tǒng)不會產(chǎn)生helloworld的備份扳还,直接產(chǎn)生helloworld,如果我們把hello放在一個變量e里面橱夭,然后將b改成String b = e+"world"; 這個時候編譯結(jié)果就不一樣了普办,a==b返回的就是false了。

問題升級

        String str2 = new String("str")+new String("01");
        str2.intern();
        String str1 = "str01";
        System.out.println(str2==str1);

首先我們了解下intern()方法徘钥,看源碼解釋:

Returns a canonical representation for the string object.
A pool of strings, initially empty, is maintained privately by the class
When the intern method is invoked,
 if the pool already contains a string equal to this {@code String} object as determined by the {@link #equals(Object)} method, then the string from the pool is returned. Otherwise, this {@code String} object is added to the pool and a reference to this {@code String} object is returned.

這個方法返回的是字符串的規(guī)范化形式(其實就是直接量)衔蹲,根據(jù)equals方法判斷常量池中是否存在這個字符串,如果存在則呈础,返回對象的引用舆驶,不存在,先將字符串緩存到常量池中然后返回該對象的引用而钞。
jdk1.6中常量池在永久代沙廉,如果字符串在常量池中找不到會將字符串拷貝到常量池中。所以str2指向的應(yīng)該還是原字符串臼节,常量池中的是拷貝撬陵。str1指向的是常量池中的拷貝珊皿,所以返回false。
jdk1.7以上版本巨税,(jdk1.8干脆常量池移到了堆中)蟋定,如果字符串在常量池中找不到不再拷貝到常量池中,而會重新生成一個對原字符串的引用草添,因此驶兜,str2指向的就是原字符串,而str1指向的也是原字符串远寸,因此抄淑,返回true。

尾聲

本章節(jié)驰后,我們了解了Java的基本數(shù)據(jù)類型和引用類型(一筆帶過肆资,面向?qū)ο蟮臅r候著重提及)和一些常用的運算。要知道灶芝,早期的計算機功能單一迅耘,只有計算功能,因此運算是最為核心的一塊功能(雖然國內(nèi)Java開發(fā)人員對于位運算并不是很熟練)监署。后面我們又提及了String類颤专,分析了String類的特殊性,和常見的一些面試題钠乏,這些面試題其實都是基于Java內(nèi)存模型的栖秕,需要多JVM較為深入才能理解,而不是記下答案就能應(yīng)付過去的晓避。下一個章節(jié)是面向?qū)ο蟠睾矗莻€時候我們根據(jù)面向?qū)ο蟮乃枷朐僬剶?shù)據(jù)結(jié)構(gòu),再見俏拱。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末暑塑,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子锅必,更是在濱河造成了極大的恐慌事格,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件搞隐,死亡現(xiàn)場離奇詭異驹愚,居然都是意外死亡,警方通過查閱死者的電腦和手機劣纲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進店門逢捺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人癞季,你說我怎么就攤上這事劫瞳√惹保” “怎么了?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵志于,是天一觀的道長涮因。 經(jīng)常有香客問我,道長恨憎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任郊楣,我火速辦了婚禮憔恳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘净蚤。我一直安慰自己钥组,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布今瀑。 她就那樣靜靜地躺著程梦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪橘荠。 梳的紋絲不亂的頭發(fā)上屿附,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天,我揣著相機與錄音哥童,去河邊找鬼挺份。 笑死,一個胖子當(dāng)著我的面吹牛贮懈,可吹牛的內(nèi)容都是我干的匀泊。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼朵你,長吁一口氣:“原來是場噩夢啊……” “哼各聘!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起抡医,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤躲因,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后忌傻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體毛仪,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年芯勘,在試婚紗的時候發(fā)現(xiàn)自己被綠了箱靴。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡荷愕,死狀恐怖衡怀,靈堂內(nèi)的尸體忽然破棺而出棍矛,到底是詐尸還是另有隱情,我是刑警寧澤抛杨,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布够委,位于F島的核電站,受9級特大地震影響怖现,放射性物質(zhì)發(fā)生泄漏茁帽。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一屈嗤、第九天 我趴在偏房一處隱蔽的房頂上張望潘拨。 院中可真熱鬧,春花似錦饶号、人聲如沸铁追。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽琅束。三九已至,卻和暖如春算谈,著一層夾襖步出監(jiān)牢的瞬間涩禀,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工然眼, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留埋泵,地道東北人。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓罪治,卻偏偏與公主長得像丽声,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子觉义,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,601評論 2 353