现在的位置: 首页 > 综合 > 正文

你是及格的java程序员吗(2)

2013年08月16日 ⁄ 综合 ⁄ 共 4457字 ⁄ 字号 评论关闭

(5)接着上篇,我们继续来说一下集合类遍历时候可能会遇见的一个小问题-ConcurrentModificationException
我们以ArrayList为例,对List进行遍历的时候,可以使用以下三种形式:
(1)使用索引
(2)使用Iterator
(3)使用增强的for循环
如果在遍历的过程中需要删除list中的元素,使用不当就会触发:java.util.ConcurrentModificationException
public static void main(String[] args) {
    List<String> list = new ArrayList<String>();
    list.add("1");list.add("2");list.add("4");list.add("6");list.add("3");
    useIndex(list);
    useIterator1(list);
    useIterator2(list);
    useEnhancedFor(list);
    //实际上,useIterator2和useEnhancedFor的这种遍历方式是等价的。
}
public static void useIndex(List<String> srcList){
    List<String> list = new ArrayList<String>(srcList);
    //使用index,没有问题
    for(int i=0;i<list.size();i++){
        String s = list.get(i);
        if(Integer.parseInt(s)%2 == 0){
            list.remove(i--);//注意这里的--,这句也可以替换成下面的两句
            //list.remove(s);
            //i--;
        }
    }
    System.out.println(list);
}
public static void useIterator1(List<String> srcList){
    List<String> list = new ArrayList<String>(srcList);
    //使用Iterator,同时使用Iterator.remove(),ok没问题
    for(Iterator<String> it = list.iterator(); it.hasNext();){
        String s = it.next();
        if( Integer.parseInt(s) % 2 == 0){
            it.remove();
        }
    }
    System.out.println(list);
}
public static void useIterator2(List<String> srcList){
    List<String> list = new ArrayList<String>(srcList);
    //使用Iterator,同时使用list.remove(),这就不可以了
    for(Iterator<String> it = list.iterator(); it.hasNext();){
        String s = it.next();
        if(Integer.parseInt(s) % 2 == 0){
            list.remove(s);
        }
    }
    System.out.println(list);
}
public static void useEnhancedFor(List<String> srcList){
    List<String> list = new ArrayList<String>(srcList);
    //使用增强的for循环,也不可以
    for(String s : list){
        if(Integer.parseInt(s) % 2 == 0){
            list.remove(s);
        }
    }
    System.out.println(list);
}
useIterator1和useIterator2的区别就在于一个是使用list.remove(),一个是使用iterator.remove().
list.iterator()会生成一个新的Iterator对象,Iterator 被创建之后会建立一个指向原来List的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,
所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出 java.util.ConcurrentModificationException 异常。
所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但可以使用 Iterator 本身的方法 remove() 来删除对象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。
6.我们接着来说一下项目中非常常用的Date
关于日期,java当中有java.util.Date、java.sql.Date、java.sql.Time、java.sql.Timestamp这四个类,java.sql.Date、java.sql.Time和java.sql.Timestamp都是java.util.Date的子类。java.sql.Date就对应数据库的date类型(年月日),java.sql.Time对应数据库的time(时分秒),java.sql.Timestamp对应数据库的timestamp(年月日时分秒),java.sql.Timestamp和java.util.Date其实差不多,但是,java.util.Date存储的秒都是整数,java.sql.Timestamp还可以存储小数的秒,因此更精确。
java.sql.Time和java.util.Date其实也差不多,它的存在只不过是为了提供一个与数据库类型对应的类,其中的大部分方法都已经被废弃掉。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Time time = new Time(System.currentTimeMillis());
System.out.println(sdf.format(time));
java.sql.Date date = new java.sql.Date(System.currentTimeMillis());
System.out.println(sdf.format(date));
java.util.Date date2 = new java.util.Date(System.currentTimeMillis());
System.out.println(sdf.format(date2));
上面三个的输出是一样的。
访问数据库时候的resultset.getDate();和preparedstatement.setDate()这里的Date是java.sql.Date,就算你的数据库存储的是年月日时分秒,但是用resultset.getDate()读出来还是会丢失掉时分秒的信息:
while(rs.next()){
    java.sql.Date birth = rs.getDate("birth");
    System.out.println(sdf.format(birth));
}
这里就会丢失掉时分秒的信息,因此需要使用rs.getTimestamp("birth");才可以。
通常,在model对象里面我们一般用java.util.Date,这就与数据库产生了不一致。因此读数据和写数据的时候,就需要转化一下,如果需要time的话还得换成是timestamp。
7.上面说到了Date,就不得不说一下日期的格式化:SimpleDateFormat
每当要进行日期格式化输出的时候,我们一般都会new一个SimpleDateFormat对象,殊不知,创建一个SimpleDateFormat实例的开销比较昂贵,解析字符串时间时频繁创建生命周期短暂的实例导致性能低下,但是SimpleDateFormat又不是线程安全的,对于这个问题的一个很好的解决办法是使用ThreadLocal模式:
public class DateUtil {
    private static ThreadLocal<Map<String,SimpleDateFormat>> dateFormatHolder = new ThreadLocal<Map<String,SimpleDateFormat>>(){
        @Override
        protected Map<String, SimpleDateFormat> initialValue() {
            Map<String, SimpleDateFormat> map = new HashMap<String, SimpleDateFormat>();
            map.put("yyyy-MM-dd", new SimpleDateFormat("yyyy-MM-dd"));
            map.put("yyyy-MM-dd HH:mm:ss", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
            return map;
        }
    };
    public static SimpleDateFormat getDateFormat(String pattern){
        Map<String, SimpleDateFormat> map = dateFormatHolder.get();
        SimpleDateFormat sdf = map.get(pattern);
        if(sdf == null){
            sdf = new SimpleDateFormat(pattern);
            map.put(pattern, sdf);
        }
        return sdf;
    }
    public static SimpleDateFormat getDateFormat10(){
        return getDateFormat("yyyy-MM-dd");
    }
    public static SimpleDateFormat getDateFormat19(){
        return getDateFormat("yyyy-MM-dd HH:mm:ss");
    }
}
参考:http://ari.iteye.com/blog/757641

抱歉!评论已关闭.