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

上了一天的课,等下18:30还得上课,趁这个时间先更新一波。


6.如何从一个多层嵌套循环中直接跳出?

for (Type type : types) {  
    for (Type t : types2) {  
         if (some condition) {  
             // Do something and break...  
             break; // 这样只退出了最里的for循环  
         }  
    }
}

比如上面的代码,只跳出了最里面的一层循环,如果要跳出两层循环,应该咋办?可以用break+label的语法,例子如下

public class Test {  
  public static void main(String[] args) {  
    outerloop:  
    for (int i=0; i < 5; i++) {  
      for (int j=0; j < 5; j++) {  
        if (i * j > 6) {  
          System.out.println("Breaking");  
          break outerloop;  
        }  
        System.out.println(i + " " + j);  
      }  
    }  
    System.out.println("Done");  
  }  
}

首先在for循环前加标签,如例子中的outerloop,然后在for循环内break label(如本例的outerloop),就会跳出该label指定的for循环。

(和goto应该是差不多道理的,话说,应该是不建议使用得吧?)

Java不提供goto语句,它虽然指定goto作为关键字,但不支持它的使 用,使程序简洁易读;尽管如此后来的c#还是支持goto语句的,goto语句一个好处就是可以保证程序存在唯一的出口,避免了过于庞大的if嵌套。
可以考虑使用goto的情形:1.从多重循环中直接跳出 ;2. 出错时清除资源; 3.可增加程序的清晰度的情况。
不加限制地使用goto:破坏了清晰的程序结构,使程序的可读性变差,甚至成为不可维护的”面条代码”。经常带来错误或隐患,比如它可能跳过了某些对象的构造、变量的初始化、重要的计算等语句。


7.如何将String转换为Int

有两种方式

String str = "10"; 
// 方法一,返回Integer类型 
Integer x = Integer.valueOf(str); 
System.out.println(x); 
// 方法二,返回int类型 
int y = Integer.parseInt(str); 
System.out.println(y);

这两种方式有一点点的不同

  • valueOf()返回的是Integer的实例
  • parseInt()返回的是基本数据类型int

类似的,Short.valueOf/parseShort等也是这样。
另外还需注意的是,在做int类型转换时,可能会抛出NumberFormatException,因此要做好异常捕获

int foo;
String StringThatCouldBeANumberOrNot = "26263Hello"; //will throw exception
String StringThatCouldBeANumberOrNot2 = "26263"; //will not throw exception
try {
      foo = Integer.parseInt(StringThatCouldBeANumberOrNot);
} catch (NumberFormatException e) {
      //Will Throw exception!
      //do something! anything to handle the exception.
}
try {
      foo = Integer.parseInt(StringThatCouldBeANumberOrNot2);
} catch (NumberFormatException e) {
      //No problem this time but still it is good practice to care about exceptions.
      //Never trust user input :)
      //do something! anything to handle the exception.
}

8.如何分割(split)string字符串

String string = "004-034556";
String[] parts = string.split("-");
String part1 = parts[0]; // 004
String part2 = parts[1]; // 034556

需要注意的是,该方法的参数是个正则表达式,要注意对某些字符做转码。例如,在正则表达式中.表示任意字符,因此,如果你要通过.号做分割,需要这样写,split(“\.”)或者split(Pattern.quote(“.”))
如果只是为了验证字符串中是否包含某个字符,使用String#contains方法就行。注意该方法的参数(CharSequence类型),不是正则表达式。


9.在java中如何对比(compare)string

  • ==对应的是指针相等,也就是他们是否为同一个对象
  • .equals()对应的是值相等,也就是逻辑相等

因此,如果你想检查两个字符串是否为相同值,那么应该用.equals()方法。

//值是相等的
new String("test").equals("test") // --> true 

// ... 值相等,但不是同个对象(指向不同的地址空间)
new String("test") == "test" // --> false 

// ... 同上
new String("test") == new String("test") // --> false 

// 这个返回true,是因为这种写法属于字符串字面量,编译器会维护一个常量池,相同的字面量,都会指向相同的一个对象
"test" == "test" // --> true 

因此, 值的对比,一般都是用equals方法。字符串字面量之间的对比,也可以用==(大家知其所以然即可,但没必要用==)

下面多举个字符串字面量的例子,下面代码中,前四个对比,返回true,最后一个返回false。

public static final String test1 = "test";
public static final String test2 = "test";

@Test
public void test() {
     // 都是字符串字面量
     String test3 = "test";
     String test = "test";

     System.out.println(test3.equals(test));
     System.out.println(test3 == test);
     System.out.println(test1.equals(test2));
     System.out.println(test1 == test2);
     System.out.println(test1 == new String("test"));
}

其他

  • 如果你重写了equal方法,记得相对应地修改hashcode方法,否则将会违反这两个方法的对等关系,如果两个对象是相等(equal)的,那么两个对象调用hashCode必须产生相同的整数结果,即:equal为true,hashCode必须为true,equal为false,hashCode也必须为false
  • 如果要忽略大小写进行对比,可以用equalsIgnoreCase()方法

10.Map<key,values>基于values排序

方法1: 使用TreeMap,可以参考下面的代码

public class Testing {  

    public static void main(String[] args) {  

        HashMap<String,Double> map = new HashMap<String,Double>();  
        ValueComparator bvc =  new ValueComparator(map);  
        TreeMap<String,Double> sorted_map = new TreeMap<String,Double>(bvc);  

        map.put("A",99.5);  
        map.put("B",67.4);  
        map.put("C",67.4);  
        map.put("D",80.3);  

        System.out.println("unsorted map: "+map);  

        sorted_map.putAll(map);  

        System.out.println("results: "+sorted_map);  
    }  
}  

class ValueComparator implements Comparator<String> {  

    Map<String, Double> base;  
    public ValueComparator(Map<String, Double> base) {  
        this.base = base;  
    }  

    // Note: this comparator imposes orderings that are inconsistent with equals.      
    public int compare(String a, String b) {  
        if (base.get(a) >= base.get(b)) {  
            return -1;  
        } else {  
            return 1;  
        } // returning 0 would merge keys  
    }  
}  

译注:如果不自己写Comparator,treemap默认是用key来排序

方法2:先通过linkedlist排好序,再放到LinkedHashMap中

public class MapUtil  
{  
    public static <K, V extends Comparable<? super V>> Map<K, V>   
        sortByValue( Map<K, V> map )  
    {  
        List<Map.Entry<K, V>> list =  
            new LinkedList<Map.Entry<K, V>>( map.entrySet() );  
        Collections.sort( list, new Comparator<Map.Entry<K, V>>()  
        {  
            public int compare( Map.Entry<K, V> o1, Map.Entry<K, V> o2 )  
            {  
                return (o1.getValue()).compareTo( o2.getValue() );  
            }  
        } );  

        Map<K, V> result = new LinkedHashMap<K, V>();  
        for (Map.Entry<K, V> entry : list)  
        {  
            result.put( entry.getKey(), entry.getValue() );  
        }  
        return result;  
    }  
}

译注:这两种方法,我简单测试了下,如果map的size在十万级别以上,两者的耗时都是几百毫秒,第二个方法会快一些。否则,第一个方法快一些。因此,如果你处理的map,都是几十万级别以下的大小,两种方式随意使用,看个人喜欢了。



看到这个特意去看了一下,以前一直对这个比较模糊,现在梳理了一下,大概总结:

  • TreeMap自然排序

按照键的自然顺序排序。Comparable接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法。实现此接口的对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。

像Integer,String这些作为键我们不用自己去实现Comparable接口,因为它内部已经帮我们实现好了。如果我们要指定自己的类作为键,那这个类就必须实现Comparable接口,并且重写compareTo(T o)方法。

- TreeMap指定顺序

TreeMap有一个构造函数,参数是一个比较器,利用这个构造函数,我们可以传入我们自己写的比较器,按照我们想要的顺序进行排序。比如我们自己定义了一个类Apple,Apple有属性重量和单价,如果想按重量来排序,我们就可以让Apple类实现Comparator接口,然后重写compare(T 01,T 02)方法,按照重量来进行排序。(比如上面的按照values排序)。

public class Test10 { 
    public static void main(String[] args) {
        Comparator x = new Apple();
        // values表示苹果个数
        TreeMap<Apple, Integer> apples = new TreeMap<Apple, Integer>(x);
        Apple a = new Apple(4.5, 10.0);
        Apple b = new Apple(3.5, 12.3);
        Apple c = new Apple(3.6, 17.2);
        Apple d = new Apple(5.3, 12.3);
        apples.put(a, 10);
        apples.put(b, 12);
        apples.put(c, 5);
        apples.put(d, 8);
        for(Map.Entry<Apple, Integer> entry:apples.entrySet()) {
            System.out.println("price = " + entry.getKey().price + "   weight = " + entry.getKey().weight     + "    number = " + entry.getValue());
        }
    }
    static class Apple implements Comparator<Apple>{ 
        public double price; 
        public double weight; 
        public Apple() { } 
        public Apple(double price, double weight) { 
            this.price = price; this.weight = weight; 
        } 
        // 按重量升序,如果重量相同,按单价降序 
        public int compare(Apple a, Apple b) { 
            if(a.weight > b.weight) { 
                return 1; 
            } else if(a.weight < b.weight) { 
                return -1; 
            } else { 
                if(a.price > b.price) { 
                    return -1; 
                } else if(a.price < b.price) { 
                    return 1; 
                } else { 
                    return 0; 
                } 
            } 
        } 
    }
}

输出

price = 4.5 weight = 10.0 number = 10
price = 5.3 weight = 12.3 number = 8
price = 3.5 weight = 12.3 number = 12
price = 3.6 weight = 17.2 number = 5

可以看到,weight从从低到高排序,weight相同时,按price从高到低排序。

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a_helloword/article/details/79981102
文章标签: Java 基础 小技巧
个人分类: Java
所属专栏: Java学习之旅
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭