记录一些简单基础但是总有时候会突然记混或者忘记的碎片化知识。
一、关于 “==”和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){
.......
}
区别很明显了