記錄一些簡單基礎但是總有時候會突然記混或者忘記的碎片化知識。
一、關於 “==”和equals()。區別一直都知道。用“==”時,如果是八大基礎類型進行則是比較他們的“值”。如果是對象則是比較所指向的地址。equals()常用於 “值“的比較。但是經常還是會犯錯誤。用一個簡單的代碼驗證。
public static void main(String[] args) {
FinalDemo f=new FinalDemo();
int b=11;
String a1="a"+"b"+1;
String b1="ab1";
String a2="a"+"b"+b;
String b2="ab11";
System.out.print("a1和b1比較結果:");
System.out.println(a1==b1);
System.out.print("a2和b2比較結果:");
System.out.println(a2==b2);
}
輸出結果。
原因:在變量a1中。由於jvm的“編譯時的優化”,默認認爲“a”、"b" 和1都是常量,因爲3個常量相加的結果是一致的。所以運行的時候就不在做計算。會把String a1="a"+"b"+1編譯成String a1="ab1"。這樣a1所指向的就和b1的指向的相同了。第一個比較結果爲true。同理可得a2和b2就不一樣了。因爲a2中存在着一個變量 int b。參考於《JAVA特種兵》一書。
二、String類的intern()方法
不做重複記錄。發現一篇研究講解很透徹的文章。
Java技術——你真的瞭解String類的intern()方法嗎
三、最簡單快速的桶排序
這個名字我居然以前沒怎麼聽過,也是醉了。。。但其實發現雖然沒聽過,但是平時用到的次數絕對不少,只是不知道叫什麼名。特此記錄。
例如對一組數排序 2,6,100,2,45,5,1。桶排序的前提是知道要排序的範圍(可能是這個限制導致,適用率太低,對名稱的熟悉度不夠)。這兒的這組數中,範圍是[0,100]。那麼定義一個大小爲101一維數組bucket[101],記錄每個數出現的次數。該數組的下標對應的就是我們要排序的數。
代碼
public static void main(String[] args) {
//需要排序的數
int[] number = new int[]{2,6,100,2,45,5,1};
//用於記錄出現次數的桶
int[] bucket=new int[101];
//記錄每個數出現的次數,(官方說法是將要排序的數放入桶中)
for(int i=0;i<number.length;i++){
bucket[number[i]]++;
}
//遍歷桶,輸出排序後的結果
for(int i=0;i<bucket.length;i++){
for(int j=0;j<bucket[i];j++){
System.out.println(i);
}
}
}
結果特性:時間複雜度較小。但是空間複雜度則比較大,所以桶排序雖簡單且快,但不適合數據跨度較大的使用場景。同時桶排序是不穩定的。由於大多數排序場景不確定數據跨度,因此桶排序很少被使用。
四、冒泡排序
基本上大家都知道的排序,但是由於效率太差很少被使用,原理就是循環的比較相鄰的數,把大的和小的分別向後和向前推。每一輪找出最大的一個。
public static void main(String[] args) {
int[] number = new int[]{2,6,100,2,45,5,1};
int temp;
for(int i=0;i<number.length-1;i++){
for(int j=0;j<number.length-i-1;j++){
if(number[j]>number[j+1]){
temp=number[j];
number[j]=number[j+1];
number[j+1]=temp;
}
}
}
for(int i=0;i<number.length;i++){
System.out.println(number[i]);
}
}
特性:限制比桶排序小,但是比較次數過多,導致效率較差。但是可以做相應的修改。1、每次排序後比較下是否排完。
public static void main(String[] args) {
boolean flag=true;
int[] number = new int[]{2,6,100,2,45,5,1};
int temp;
for(int i=0;i<number.length-1;i++){
if(!flag){
for(int j=0;j<number.length-i-1;j++){
if(number[j]>number[j+1]){
temp=number[j];
number[j]=number[j+1];
number[j+1]=temp;
}
}
}
for(int j=0;j<number.length-i-1;j++){
if(number[j]>number[j+1])
flag=false;
}
}
for(int i=0;i<number.length;i++){
System.out.println(number[i]);
}
}
優缺點:對有些數據比如 1,2,3,4,5,6,7,8 可能能很快結束排序。但是如果是8,7,6,5,4,3,2,1反而更加耗時。不建議使用。2、標記法
定義一個boolean變量flag。只要是每次出現順序替換的情況就將變量設置爲false。每輪結束後判斷flag就可以看出是否排序完成。
public static void main(String[] args) {
boolean flag=true;
int[] number = new int[]{2,6,100,2,45,5,1};
int temp;
for(int i=0;i<number.length-1;i++){
for(int j=0;j<number.length-i-1;j++){
if(number[j]>number[j+1]){
temp=number[j];
number[j]=number[j+1];
number[j+1]=temp;
flag=false;
}
}
if(flag){
break;
}
}
for(int i=0;i<number.length;i++){
System.out.println(number[i]);
}
}
五、快速排序。
以前總以爲自己知道這個,最近想自己要寫一下的時候才知道自己一直在偏自己。
原理:每次在需要排序的數中選一個作爲標準數,分別從右到左和從左到右對需要排序的部分進行比較,找到第一個比標準數大或者小的數,然後與標準數替換,最後是比標準大數全部放右邊,小的全部放左邊,依次反覆得到最佳結果。
public static void quickSort(int[] number,int begin,int end){
if(begin<end){
//標準數
int key=number[begin];
int i=begin;
int j=end;
while(i<j){
//找出從右到左第一個比標準數要小的數
while(i<j&&number[j]>key){
j--;
}
//將從右到左第一個比標準數小的和標準數互換
if(i<j){
number[i]=number[j];
//這一部分其實省略了一句代碼
//number[j]=key;
i++;
}
//找出從左到右第一個比標準數大的數
while(i < j && number[i]<key){
i++;
}
//將找到的數和標準數互換
if(i < j){
number[j] = number[i];
//同樣,這部分也省略了一部分代碼
//number[i]=key;
j--;
}
}
//一輪結束後,分爲兩部分,左邊的全是比標準數小的,右邊全是比它大的,因爲上面省略了代碼。所以下面需要把最後的一個空位置留給key
number[i] = key;
//對剩餘的兩部分繼續重複
quickSort(number, begin, i-1);
quickSort(number, i+1, end);
}
}
public static void main(String[] args) {
int[] number = new int[]{2,6,100,2,45,5,1};
quickSort(number,0,6);
for(int i=0;i<number.length;i++){
System.out.println(number[i]);
}
}
特點:需排序數多的情況下性能比其他的快,否則和其他排序法性能差不多,如果排序的數本身就是有序的情況下性能最差。大數據量的情況下,適合和插入排序法一起使用。先用快速排序法將數據分爲幾個區域較小但是大致有序區間,然後使用插入排序法。
六、插入排序
分爲直接插入和二分插入。插入法會將待排序數據默認分爲兩個部分:排好序部分和待排序部分。如果是直接插入法可以默認其中第一個數爲排好序的部分,然後拿其餘的待排序部分去和第一個數比,判斷插入到合適的位置。此時排好序的數據就有兩個了,接着繼續重複上面的步驟,直到待排序數據全部插入到排好序的部分。二分插入則是對直接插入的優化。每次取排好序數據中的對半位置的數進行比較。
直接插入
public static void Sort(int [] number){
int temp;
for(int i=1;i<=number.length-1;i++){
temp=number[i];
//與排好序的部分進行比較,第一次默認爲第一個數,後續會逐漸增多
for(int j=i-1;j>=0;j--){
if(number[j]>temp){
number[j+1]=number[j];
number[j]=temp;
}else{
break;
}
}
}
for(int i=0;i<number.length;i++){
System.out.println(number[i]);
}
}
二分插入public static void Sort(int[] number ){
int temp,start,end,mid;
//同直接排序一樣,以第一個爲默認排好序的部分
for(int i=1;i<=number.length-1;i++){
temp=number[i];
//對排好序的部分進行二分,以此比較
start=0;
//排好序的部分最大位置範圍
end=i-1;
mid=0;
while(start<=end){
mid=(start+end)/2;
//現有數據對摺比較,如果大於則取前面一部分,小於則取後面一部分繼續比較。
if(number[mid]>temp){
end=mid-1;
}else{
start=mid+1;
}
}
//排除位置不變的情況 i與start相等的時候表明位置不變
if(i!=start){
//位置有改變,開始插入的部分向後移動
for(int j=i;j>start;j--){
number[j]=number[j-1];
}
//空出來的位置填入進行比較的數【temp】
number[start]=temp;
}
}
for(int i=0;i<number.length;i++){
System.out.println(number[i]);
}
}
public static void main(String[] args) {
int[] number = new int[]{2,6,100,2,45,5,1};
Sort(number);
}
還有幾種等有空在補充。分別是希爾排序、選擇排序、堆排序、歸併排序。
框架:
springmvc靜態資源無法訪問以及配置導致可以訪問靜態資源但是無法訪問controller。
經常發現頁面中的js無法訪問,這是因爲springMvc需要對靜態資源進行配置。一般用如下配置即可,默認根目錄從webapp開始。主要原因是springMvc原來沒辦法較好的處理各種靜態資源的訪問。需要在請求後帶各種後綴。如果不帶後綴則需要自己進行配置。
<mvc:resources location="/WEB-INF/view/pages" mapping="/pages/**"/>
<mvc:resources location="/WEB-INF/view/images/" mapping="/images/**"/>
<mvc:resources location="/WEB-INF/view/javasrcipt/" mapping="/javasrcipt/**"/>
<mvc:resources location="/WEB-INF/view/bootstrap/" mapping="/easyui/**"/>
<mvc:resources location="/WEB-INF/view/css/" mapping="/css/**"/>
<mvc:resources location="/WEB-INF/view/jquery/" mapping="/jquery/**"/>
對應的jsp頁面如下就能訪問到靜態資源。
<%String path = request.getContextPath();%>
<script src="<%=path%>/jquery/jquery.min.js"></script>
<script src="<%=path%>/bootstrap/js/bootstrap.js"></script>
但是這樣弄了之後可能導致你的controller無法訪問了。
只需要在配置靜態資源的最上方加一句 <mvc:annotation-drivern/>就可以了
<mvc:annotation-driven />
<mvc:resources location="/WEB-INF/view/pages" mapping="/pages/**"/>
<mvc:resources location="/WEB-INF/view/images/" mapping="/images/**"/>
<mvc:resources location="/WEB-INF/view/javasrcipt/" mapping="/javasrcipt/**"/>
<mvc:resources location="/WEB-INF/view/bootstrap/" mapping="/easyui/**"/>
<mvc:resources location="/WEB-INF/view/css/" mapping="/css/**"/>
<mvc:resources location="/WEB-INF/view/jquery/" mapping="/jquery/**"/>
還有一種方法就是在web.xml進行配置,這樣就不需要在springMvc中配置了
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.png</url-pattern>
<url-pattern>*.js</url-pattern>
<url-pattern>*.jpg</url-pattern>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
註解:@Autowired和@Resource
對類成員變量、方法及構造函數進行標註,完成自動裝配的工作。 消除 set ,get方法。
例如,User類擁有name和age兩個屬性。
圖片等價於下面的xml配置
<bean id="controller" class="com.y.demo.controller"/>
<bean id="user" class="com.y.demo.User">
<property name="name" value="用戶1"/>
<property name="age" value="18"/>
</bean>
</bean>
使用@Autowired必須在xml裏面做一下聲明<bean class="org.springframework.beans.factory.annotation. AutowiredAnnotationBeanPostProcessor "/>
@Resource的用處和@Autowired相似,主要差別是@Autowired是根據類型注入。用上面的例子說就是注入到bean裏面是通過User這個類來進行的,後續查找使用也是根據bean的類型進行查找。
此時圖中對應的xml爲下面的樣子
<bean id="controller" class="com.y.demo.controller"/>
<bean id="user1" class="com.y.demo.User">
<property name="name" value="用戶1"/>
<property name="age" value="18"/>
</bean>
</bean>
使用@Resource必須的聲明如下
<bean class="org.springframework.beans.factory.annotation. CommonAnnotationBeanPostProcessor"/>
@RequestParam和@PathVariable的區別 摘抄自此處 http://blog.csdn.net/u011410529/article/details/66974974
@RequestParam
和 @PathVariable
註解是用於從request中接收請求的,兩個都可以接收參數,關鍵點不同的是@RequestParam
是從request裏面拿取值,而 @PathVariable
是從一個URI模板裏面來填充
@RequestParam
看下面一段代碼:
http://localhost:8080/springmvc/hello/101?param1=10¶m2=20
根據上面的這個URL,你可以用這樣的方式來進行獲取
public String getDetails(
@RequestParam(value="param1", required=true) String param1,
@RequestParam(value="param2", required=false) String param2){
...
}
@RequestParam
支持下面四種參數
- defaultValue 如果本次請求沒有攜帶這個參數,或者參數爲空,那麼就會啓用默認值
- name 綁定本次參數的名稱,要跟URL上面的一樣
- required 這個參數是不是必須的
- value 跟name一樣的作用,是name屬性的一個別名
@PathVariable
這個註解能夠識別URL裏面的一個模板,我們看下面的一個URL
http://localhost:8080/springmvc/hello/101?param1=10¶m2=20
上面的一個url你可以這樣寫:(請求路徑裏面的id,當成模板來運用)
@RequestMapping("/hello/{id}")
public String getDetails(@PathVariable(value="id") String id,
@RequestParam(value="param1", required=true) String param1,
@RequestParam(value="param2", required=false) String param2){
.......
}
區別很明顯了