Java编程的一些小技巧-----基础语法篇(1)

今天在github上面看到了一个很好的项目,是在Stack Overflow上面点赞数top100的关于Java的回答,看了一些,感觉十分实用,对于新手来说,能加深对Java的认识,同时也能让代码更简洁。所以想写下这系列的博文,每个回答我都会亲自用代码检验一下,下面一起来看看这些小技巧吧,绝不会让你失望。

1.Java +=操作符实质

看了这个是不是觉得这有啥难的,不就是一个加法吗?但还真不是这么简单。

可以试试在编辑器中输入以下代码

int a = 5;
double b = 10.5;
a = a + b; // 这行编译出错
a += b; // 这行没有问题
a = a + (int)b; //这行也没问题

是不是感觉有点惊讶?a = a + b;不能通过,a += b;怎么就能通过了呢?其实再看这个回答之前,我也一直以为a += b其实就等同于a = a + b;然后事实明显不是这样。那这是什么原因呢?看看官方文档的解释就知道了。
这里写图片描述
意思就是对于E1 op= E2这样的表达式来说,等同于(T)(E1 op E2)。op=诸如+=、-=、*=、/=这样的运算符,E1和E2表示两个操作数,T表示E1的数据类型。那么我们上面的代码中a += b;就变成了(int)(a + b);

2.将InputStream转化为String

使用apache库我就不说了,因为我也没用过,我们就看看自己写一个函数怎么搞。

/**
 * 将InputStream转化为String
 * @param is
 * @return
 */ 
static String convertStreamToString(InputStream is) { 
    @SuppressWarnings("resource") 
    // \A表示文件的开头 
    Scanner read = new Scanner(is).useDelimiter("\\A"); 
    return read.hasNext() ? read.next() : ""; 
}

写个主函数测试一下

FileInputStream fis = new FileInputStream("test.txt"); 
System.out.println(convertStreamToString(fis));

完全没毛病,大家可以自己试试。

3.将数组转化为List

相信有挺多人和我一样,要么用循环,遍历数组把数组的值一个一个赋值给List。。。这是最傻逼的方法。再者,就是使用Arrays.asList()方法。用这个方法的确没毛病,但却是有坑滴。

  • 这样生成的List是定长的,意味着你不能进行remove和add操作,不然会抛出UnsupportedOperationException。(好吧,难怪我说以前怎么用这个方法总报错,现在终于找到答案了)
  • 如果修改数组的值,则List中的值也会变。

之所以会出现这样的情况,是因为Arrays.asList()方法返回的是Arrays的内部静态类,而不是Java.util.ArrayList的类。这个java.util.Arrays.ArrayList有set(),get(),contains()方法,但是没有任何add() 方法,所以它是固定大小的。

如果你希望避免这两个坑,请使用下面的方式

Collections.addAll(arraylist, array);

新技能get。我们来看看代码

Integer[] a = new Integer[]{1, 2, 3}; 
List<Integer> r = new ArrayList<Integer>(); 
r = Arrays.asList(a); 
//Collections.addAll(r, a); 
//r.add("d"); 
//a[0] = 10;
System.out.println(r);

这里需要提醒的是,如果你是基本类型比如int类型的数组,也应该使用Integer来进行包装,不然会报错。

4.Map遍历

在Java中有多种遍历HashMap的方法。让我们回顾一下最常见的方法和它们各自的优缺点。由于所有的Map都实现了Map接口,所以接下来方法适用于所有Map(如:HaspMap,TreeMap,LinkedMap,HashTable,etc)

方法一:使用for-each迭代entries

这是最常见的方法,并在大多数情况下更可取的。当你在循环中需要使用Map的键和值时,就可以使用这个方法

for(Map.Entry<Integer, String> entry:map.entrySet()) { 
    Integer key = entry.getKey(); 
    String value = entry.getValue(); 
}

注意:For-Each循环是Java5新引入的,所以只能在Java5以上的版本中使用。如果你遍历的map是null的话,For-Each循环会抛出NullPointerException异常,所以在遍历之前你应该判断是否为空引用。

方法二:使用for-each迭代keys和values

如果你只需要用到map的keys或values时,你可以遍历KeySet或者values代替entrySet

for(Integer i:map.keySet()) { 
    System.out.println(i); 
} 
for(String s:map.values()) { 
    System.out.println(s); 
}

这个方法比entrySet迭代具有轻微的性能优势(大约快10%)并且代码更简洁

方法三:使用Iterator迭代

使用泛型

Iterator<Map.Entry<Integer, String>> entries = r.entrySet().iterator(); 
while(entries.hasNext()) { 
    Map.Entry<Integer, String> entry = entries.next(); 
    Integer key = entry.getKey(); 
    String value = entry.getValue(); 
    System.out.println(key + ":" + value); 
}

不使用泛型(算了,还是推荐大家使用泛型吧。。。)

你可以使用同样的技术迭代keyset或者values

这个似乎有点多余但它具有自己的优势。首先,它是遍历老java版本map的唯一方法。另外一个重要的特性是可以让你在迭代的时候从map中删除entries的(通过调用iterator.remover())唯一方法.如果你试图在For-Each迭代的时候删除entries,你将会得到unpredictable resultes 异常。

从性能方法看,这个方法等价于使用For-Each迭代

方法四:迭代keys并搜索values(低效率,好吧,我就是一直用的这种低效率的方法)

for (Integer key : map.keySet()) { 
    Integer value = map.get(key); 
    System.out.println("Key = " + key + ", Value = " + value); 
}

这个方法看上去比方法#1更简洁,但是实际上它更慢更低效,通过key得到value值更耗时(这个方法在所有实现map接口的map中比方法#1慢20%-200%)。如果你安装了FindBugs,它将检测并警告你这是一个低效的迭代。这个方法应该避免。

总结

如果你只需要使用key或者value使用方法#2,如果你坚持使用java的老版本(java 5 以前的版本)或者打算在迭代的时候移除entries,使用方法#3。其他情况请使用#1方法。避免使用#4方法。

5.如何测试一个数组中是否包含指定的值

excuse me???这么简单,不就是一个循环遍历吗??

简单而优雅的方法(好,这个技能掌握了)

String[] values = {"A", "B", "C", "D"};
if(Arrays.asList(values).contains("A")) { 
    System.out.println("6666"); 
} else { 
    System.out.println("5555"); 
}

自己写逻辑

问题的本质,其实是一个查找的问题,即查找一个数组是否包含某个值。对于原始类型,若是无序的数组,可以直接写一个 for 循环:

for(String s:values) { 
    if(s.equals("A")) { 
        return true; 
    } else { 
        return false; 
    } 
}

若是有序的数组,可以考虑二分查找或者其他查找算法:

public static boolean useArraysBinarySearch(String[] arr, String targetValue) {
      int a =  Arrays.binarySearch(arr, targetValue);
      if(a >= 0)
         return true;
      else
         return false; 
}

若数组里包含的是一个个对象,实际上比较就是引用是否相等(String 类型是判断 值是否相等),本质就是比较 hashcode 和 equal 方法,可以考虑使用 List 或者 Set,如下

public static boolean useList(String[] arr, String targetValue) {     
    return Arrays.asList(arr).contains(targetValue); 
}
for(String s:values) { 
    if(s.equals("A")) { 
        return true; 
    } else { 
        return false; 
    } 
}

好了,今天先写5个问题,去吃饭了。越写越有意思,本渣渣表示很惊奇啊,欲知后事如何,请看明天的博文。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值