java--集合、基础类库相关知识点

摘自《疯狂java讲义》

BigDecimal问题
当使用new BigDecimal(double val)构造器时会有计算不准确问题,如果使用BigDecimal(String val)构造器结果是可预知的,如果必须使用double浮点数作为BigDecimal构造器的参数们可以使用BigDecimal.valueOf(double value)静态方法来创建BigDecimal对象。
BigDecimal.valueOf(double value)源码

public static BigDecimal valueOf(double val) {
        if (Double.isInfinite(val) || Double.isNaN(val)) {
            throw new NumberFormatException("Infinity or NaN: " + val);
        }
        return new BigDecimal(Double.toString(val));
    }

最后还是调用的 new BigDecimal(String value)

foreach该循环中迭代的变量不是集合元素本身,系统只是依次把集合元素的值赋给迭代变量

HashSet判断两个元素相等的机制
HashSet判断两个元素相等的标准是两个对象通过equals方法比较相等,并且两个对象的hashCode方法返回值也相等
当把一个对象放入HashSet中时,如果需要重写该对象对应类的equals方法,则也应该重写hashCode方法,规则是:如果两个对象都通过equals方法比较返回true,则这两个hashCode值也相同
若两个对象的hashCode方法返回的值相同,但是通过equals方法比较返回的是false。由于hashCode值相同,HashSet将试图把他保存在同一个位置,但不行,所以实际上会在这个位置用链式结构来保存多个对象,而HashSet访问集合元素时,也是根据元素的hashCode值来快速定位的,如果HashSet中两个以上元素具有相同的HashCode值,将会导致性能下降

如果向HashSet中添加一个可变对象,后面的程序修改了该可变对象的实例变量,则可能导致他与集合中的其他元素相同(即两个对象的equals方法返回true,两个hashCode相等)
eg

public class Test{

   public static void main(String[] args)
   {
      HashSet hs = new HashSet();
      hs.add(new R(5));
      hs.add(new R(-3));
      hs.add(new R(9));
      hs.add(new R(-2));

      System.out.println(hs);

      Iterator it = hs.iterator();
      R first = (R) it.next();

      first.count = -3;

      System.out.println(hs);

      hs.remove(new R(-3));

      System.out.println(hs);

      System.out.println(hs.contains(new R(-3)));

      System.out.println(hs.contains(new R(-2)));

   }

   static class R{
      int count;

      public R(int count){
         this.count = count;
      }

      @Override
      public String toString() {
         return count+"";
      }

      @Override
      public boolean equals(Object obj) {
         if(obj == this){
            return true;
         }
         if(obj != null && obj.getClass() == R.class){
            return this.count == count;
         }

         return false;
      }

      @Override
      public int hashCode() {
         return count;
      }
   }
}

输出结果:
[-2, -3, 5, 9]
[-3, -3, 5, 9]
[-3, 5, 9]
false
true

本例当试图删除count=-3的R对象时,HashSet会计算出该对象的equals方法进行比较,如果相等则删除该对象(HashSet实际上只有第二个元素满足条件,第一个元素实际上保存在count=-2的位置上),所以删除第二个元素。

TreeSet
自然排序,TreeSet会调用集合元素的compareTo方法来比较元素之间的大小关系,然后将集合元素按升序排序。
向TreeSet集合中添加元素时,只有第一个元素无需实现Comparable接口,后面添加的所有元素必须实现Comparable接口
如果向往TreeSet能够正常工作,TreeSet只能添加同一种类型的对象
当需要把一个对象放入TreeSet中,重写该对象对应的类的equals方法时,应保证该方法与compareTo方法有一致的结果
eg

public class Test{

   public static void main(String[] args)
   {
      TreeSet hs = new TreeSet();
      hs.add(new R(5));
      hs.add(new R(-3));
      hs.add(new R(9));
      hs.add(new R(-2));

      System.out.println(hs);

      Iterator it = hs.iterator();
      R first = (R) it.next();

      first.count = 20;

      R last = (R) hs.last();
      last.count = -2;

      System.out.println(hs);

      System.out.println(hs.remove(new R(-2)));
      System.out.println(hs);

      System.out.println(hs.remove(new R(5)));
      System.out.println(hs);

      System.out.println(hs.remove(new R(-2)));
      System.out.println(hs);

      System.out.println(hs.remove(new R(-2)));
      System.out.println(hs);



   }

   static class R implements Comparable{
      int count;

      public R(int count){
         this.count = count;
      }

      @Override
      public String toString() {
         return count+"";
      }

      @Override
      public boolean equals(Object obj) {
         if(obj == this){
            return true;
         }
         if(obj != null && obj.getClass() == R.class){
            return this.count == count;
         }

         return false;
      }

      @Override
      public int hashCode() {
         return count;
      }

      @Override
      public int compareTo(Object o) {
         R r = (R) o;
         return count > r.count?1:count<r.count?-1:0;
      }
   }
}

输出结果:
[-3, -2, 5, 9]
[20, -2, 5, -2]
false
[20, -2, 5, -2]
true
[20, -2, -2]
true
[20, -2]
true
[20]
一旦改变了TreeSet集合里的可变元素的实例变量,当再试删除该对象时,TreeSet也会删除失败(甚至集合中原有的,实例变量没有修改后元素相等的元素也无法删除)
当执行完hs.remove(new R(5))后,TreeSet会对集合中的元素重新索引(不是重新排序),接下来就可以删除TreeSet中的所有元素了,包括那些被修改过的实例变量元素

TreeSet判断两个元素相等的标准是:通过comparator比较两个元素返回了0;

List删除机制

public class Test{

   public static void main(String[] args)
   {
      List list = new ArrayList();
      list.add("1111");
      list.add("22222");
      list.add("3333");
      System.out.println(list);
      list.remove(new A());
      System.out.println(list);
      list.remove(new A());
      System.out.println(list);

   }

   static class A{
      @Override
      public boolean equals(Object obj) {
         return true;
      }
   }
}

输出结果:
[1111, 22222, 3333]
[22222, 3333]
[3333]
由上述可知,List将会调用该A对象的equals方法依次与集合元素进行比较,如果该equals方法以某个集合元素为参数时返回true,List将会删除该元素

固定长度List
Arrays工具类中的asList(Object…a)方法,该方法可以把一个数组或者指定个数的对象换成一个List集合,这个List集合既不是ArrayList实现类,也不是Vector实现类,而是Arrays的内部类ArrayList的实例,其实一个固定长度的List集合,程序只能遍历访问集合里的元素,不可增加删除元素

Map
Map的Key不允许重复,即同一个Map对象的任何两个Key通过equals方法比较总是返回false

HashMap的可以是null,但是还能存在一个
eg:

public class Test{

   public static void main(String[] args)
   {
      HashMap hm = new HashMap();

      hm.put(null,null);
      System.out.print(hm);
   }

}

输出结果:
{null=null}

与HashSet类似,如果使用可变对象作为HashMap的key,并且程序修改了key对象则会出现与HashSet类似额问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值