基础笔记(后端)

记录一些简单基础但是总有时候会突然记混或者忘记的碎片化知识。

一、关于 “==”和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的类型进行查找。

如果使用@Resource(name="user1")来进行注解,  通过此注解完成从spring配置文件中查找名称为user1的bean来装user,如果spring配置文件中不存在 user1名称的bean则转向按照bean的类型经行查找,也就查看有没有叫做 user1的类。

此时图中对应的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&param2=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&param2=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){
.......
}

区别很明显了


常用注解


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章