2021-04-18

Java容器学习心得
y成功运行的java容器
翁恺老师讲的ArrayList里装的是String,我试了一下能不能装int,报错,说是基本数据类型不能做形参,欧,懂了。根据提示换成Integer就好了。
每次都要再写一遍notes.add(),一次能多加吗?在这里插入图片描述
这肯定不行,add是ArrayList类里定义好的一个方法。我真呆。
在这里插入图片描述
这里面的数可以相等。
step into和step over的区别调试的时候一个不跳过子函数,一个跳过子函数
在这里插入图片描述
这是成功的,刚刚忘写return notes.get(s)的return
return的就是最后经过函数变换之后s的模样吧。
在这里插入图片描述
这样为啥不行?
我觉得是get方法在ArrayList类里,并不在collection类里,而a是class collection的实例对象。notes对象是ArrayList的实例对象,所以它可以调用ArrayList的方法get。我明白了。
add方法一般都不返回,类型是void。
在这里插入图片描述
Integer不是基本数据类型,它是个类,属于java.lang
在这里插入图片描述

集合

1 vector 2 bitset 3 stack 4 hashtable

1. 集合

缺点是
将对象置入一个集合时丢失了类型信息。之所以会发生这种情况,是因为当时编写集合类时,程序员不知道用户到底想把什么类型置入集合。若指示某个集合只允许特定的类型,会妨碍它成为一个“常规用途”的工具,为用户带来麻烦。为解决这个问题,集合实际上容纳的是Object的一些对象的句柄。这种类型当然代表Java中的所有对象,因为它是所有类的根。当然,Object不包括基本数据类型,因为基本数据类型不是从“任何东西”继承来的.
它不适用于:
*(1)将一个对象句柄置入集合时,由于类型信息会被抛弃,所以所有类型的对象都可以进入我们的集合——即便特别指示它只能容纳特定类型的对象。{example:虽然指示它只能容纳猫,但事实上任何人都可以把一条狗扔进来。}
(2)由于类型信息不复存在,所以集合能唯一肯定的事情就是自己容纳的是指向一个对象的句柄。正式使用之前,必须对其进行造型,使其具有正确的类型。
值得欣慰的是,Java不允许人们滥用置入集合的对象。{example:人们将一只狗扔进一个猫的集合,那么仍会将集合内的所有东西看作猫,所以在使用那条狗时会得到一个“违例”。
若要把那条狗的句柄“造型”到一只猫,在运行期间仍会违例。

*```java
`class Cat{
      private int catNumber;
      Cat(int i){
          catNumber=i;
          }
        void print(){
 
 System.out.println`("Cat #"+catNumber);
    }
 }
 class Dog{
    private int dogNumber;
   Dog (int i){
      dogNumber=i;
      }
    void print(){
    System.out.println("Dog #"+dogNumber);
    }
 }
 public class CatsAndDogs{
      public static void main (String[] args){
      Vector cats=new Vector();
      for(int i=0;i<7;i++)
        cats.addElement(new Cat(i));
        //not a problem to add a dog to cats:
        cats.addElement(new Dog(7));
        for(int i=0;i<cats.size();i++)
           ((Cat)cats.elementAt(i)).print();
           //Dog is detected only at run-time
           }
     }

Vector

1、先创建一个
2、addElement添加元素
3、elementAt取得元素
4、调用size()方法,可使我们知道已经添加了多少元素,以便防止误超边界,导致违例。
5、elements()获得对vector的“枚举”

bitset

1、实际上是由“二进制位”构成的一个vector
2、如果希望高效率保存大量“开关”信息,就应使用Bitset;它只有从尺寸的角度看才有意义;如果希望的高效率的访问,那么它的速度会比使用一些固有类型的数组慢一些。
3、BitSet的最小长度是一个长整数(Long)的长度:64位。这意味着假如我们准备保存比这更小的数据,如8位数据,那么BitSet就显得浪费了。所以最好创建自己的类,用它容纳自己的标志位。
4、在一个普通的Vector中,随我们加入越来越多的元素,集合也会自我膨胀。在某种程度上,BitSet也不例外。


```java
//: Bits.java
// Demonstration of BitSet
import java.util.*;
public class Bits {
  public static void main(String[] args) {
    Random rand = new Random();
    // Take the LSB of nextInt():
    byte bt = (byte)rand.nextInt();
    BitSet bb = new BitSet();
    for(int i = 7; i >=0; i--)
      if(((1 << i) &  bt) != 0)
        bb.set(i);
      else
        bb.clear(i);
    System.out.println("byte value: " + bt);
    printBitSet(bb);
    short st = (short)rand.nextInt();
    BitSet bs = new BitSet();
    for(int i = 15; i >=0; i--)
      if(((1 << i) &  st) != 0)
        bs.set(i);
      else
        bs.clear(i);
    System.out.println("short value:" + st);
    printBitSet(bs);
    int it = rand.nextInt();
    BitSet bi = new BitSet();
    for(int i = 31; i >=0; i--)
      if(((1 << i) &  it) != 0)
        bi.set(i);
      else
        bi.clear(i);
    System.out.println("int value: " + it);
    printBitSet(bi);
    // Test bitsets >= 64 bits:
    BitSet b127 = new BitSet();
    b127.set(127);
    System.out.println("set bit 127: " + b127);
    BitSet b255 = new BitSet(65);
    b255.set(255);
    System.out.println("set bit 255: " + b255);
    BitSet b1023 = new BitSet(512);
// Without the following, an exception is thrown
// in the Java 1.0 implementation of BitSet:
//    b1023.set(1023);
    b1023.set(1024);
    System.out.println("set bit 1023: " + b1023);
  }
  static void printBitSet(BitSet b) {
    System.out.println("bits: " + b);
    String bbits = new String();
    for(int j = 0; j < b.size() ; j++)
      bbits += (b.get(j) ? "1" : "0");
    System.out.println("bit pattern: " + bbits);
  }
} ///:~

随机数字生成器用于创建一个随机的byte、short和int。每一个都会转换成BitSet内相应的位模型。此时一切都很正常,因为BitSet是64位的,所以它们都不会造成最终尺寸的增大。但在Java 1.0中,一旦BitSet大于64位,就会出现一些令人迷惑不解的行为。假如我们设置一个只比BitSet当前分配存储空间大
出1的一个位,它能够正常地扩展。但一旦试图在更高的位置设置位,同时不先接触边界,就会得到一个恼人的违例。这正是由于BitSet在Java 1.0里不能正确扩展造成的。本例创建了一个512位的BitSet。构建器分配的存储空间是位数的两倍。所以假如设置位1024或更高的位,同时没有先设置位1023,就会在Java1.0里得到一个违例。但幸运的是,这个问题已在Java 1.1得到了改正。所以如果是为Java 1.0写代码,请尽量避免使用BitSet。

Stack

1、Stack有时也可以称为“后入先出”(LIFO)集合。换言之,我们在堆栈里最后“压入”的东西将是以后第一个“弹出”的。和其他所有Java集合一样,我们压入和弹出的都是“对象”,所以必须对自己弹出的东西进行“造型”
2、一种很少见的做法是拒绝使用Vector作为一个Stack的基本构成元素,而是从Vector里“继承”一个
Stack。这样一来,它就拥有了一个Vector的所有特征及行为,另外加上一些额外的Stack行为。很难判断
出设计者到底是明确想这样做,还是属于一种固有的设计。
3、下面是一个简单的堆栈示例,它能读入数组的每一行,同时将其作为字串压入堆栈。

//: Stacks.java
// Demonstration of Stack Class
import java.util.*;
public class Stacks {
  static String[] months = {
    "January", "February", "March", "April",
    "May", "June", "July", "August", "September"public static void main(String[] args) {
    Stack stk = new Stack();
    for(int i= 0; i < months.length; i++)
      stk.push(months[i] + " ");
    System.out.println("stk = " + stk);
2
// Treating a stack as a Vector:
    stk.addElement("The last line");
    System.out.println(
      "element 5 = " + stk.elementAt(5));
    System.out.println("popping elements:");
    while(!stk.empty())
      System.out.println(stk.pop());
  }
}

months数组的每一行都通过push()继承进入堆栈,稍后用pop()从堆栈的顶部将其取出。要声明的一点是——Vector操作亦可针对Stack对象进行。这可能是由继承的特质决定的——Stack“属于”一种Vector。因此,能对Vector进行的操作亦可针对Stack进行,例如elementAt()方法。

Hashtable

Vector允许我们用一个数字从一系列对象中作出选择,所以它实际是将数字同对象关联起来了。但假如我们想根据其他标准选择一系列对象呢?堆栈就是这样的一个例子:它的选择标准是“最后压入堆栈的东西”。这种“从一系列对象中选择”的概念亦可叫作一个“映射”、“字典”或者“关联数组”。从概念上讲,它
看起来象一个Vector,但却不是通过数字来查找对象,而是用另一个对象来查找它们!这通常都属于一个程序中的重要进程。在Java中,这个概念具体反映到抽象类Dictionary身上。该类的接口是非常直观的

  1. size()告诉我们其中包含了多少元素; isEmpty()判断是否包含了元素(是则为true); put(Object key,

  2. Object value)添加一个值(我们希望的东西),并将其同一个键关联起来(想用于搜索它的东西);

  3. get(Object , key)获得与某个键对应的值;

  4. remove(Object Key)用于从列表中删除“键-值”对

  5. 还可以使用枚举技术:keys()产生对键的一个枚举(Enumeration);

  6. 而elements()产生对所有值的一个枚举。

这便是一个Dictionary(字典)的全部。Dictionary的实现过程并不麻烦。下面列出一种简单的方法,它使用了两个Vector,一个用于容纳键,另一个用来容纳值:


```java

```java
//: AssocArray.java
// Simple version of a Dictionary
import java.util.*;
public class AssocArray extends Dictionary {
  private Vector keys = new Vector();
  private Vector values = new Vector();
  public int size() { return keys.size(); }
  public boolean isEmpty() {
    return keys.isEmpty();
  }
  public Object put(Objectkey, Object value) {
    keys.addElement(key);
    values.addElement(value);
    return key;
  }
  public Object get(Object key) {
    int index = keys.indexOf(key);
    // indexOf() Returns-1 if key not found:
    if(index ==-1) return null;
    return values.elementAt(index);
  }
  public Object remove(Object key) {int index = keys.indexOf(key);
 if(index ==-1) return null;
    keys.removeElementAt(index);
    Object returnval = values.elementAt(index);
    values.removeElementAt(index);
    return returnval;
  }
  public Enumeration keys() {
    return keys.elements();
  }
  public Enumeration elements() {
    return values.elements();
  }
  // Test it:
  public static void main(String[] args) {
    AssocArray aa = new AssocArray();
    for(char c = 'a'; c <= 'z'; c++)
      aa.put(String.valueOf(c),
             String.valueOf(c)
             .toUpperCase());
    char[] ca = { 'a', 'e', 'i', 'o', 'u' };
    for(int i = 0; i < ca.length; i++)
      System.out.println("Uppercase: " +
             aa.get(String.valueOf(ca[i])));
  }
} ///:~

在对AssocArray的定义中,我们注意到的第一个问题是它“扩展”了字典。这意味着AssocArray属于Dictionary的一种类型,所以可对其发出与Dictionary一样的请求。如果想生成自己的Dictionary,而且就在这里进行,那么要做的全部事情只是填充位于Dictionary内的所有方法(而且必须覆盖所有方法,因为它们——除构建器外——都是抽象的)。Vector key和value通过一个标准索引编号链接起来。也就是说,如果用“roof”的一个键以及“blue”的一个值调用put()——假定我们准备将一个房子的各部分与它们的油漆颜色关联起来,而且AssocArray里已
有100个元素,那么“roof”就会有101个键元素,而“blue”有101个值元素。而且要注意一下get(),假如我们作为键传递roof”,它就会生成与keys.index.Of()的索引编号,然后用那个索引编号生成相关的值矢量内的值。
main()中进行的测试是非常简单的;它只是将小写字符转换成大写字符,这显然可用更有效的方式进行。但它向我们揭示出了AssocArray的强大功能。
标准Java库只包含Dictionary的一个变种,名为Hashtable(散列表,注释③)。Java的散列表具有与AssocArray相同的接口(因为两者都是从Dictionary继承来的)。但有一个方面却反映出了差别:执行效率。若仔细想想必须为一个get()做的事情,就会发现在一个Vector里搜索键的速度要慢得多。但此时用散列表却可以加快不少速度。不必用冗长的线性搜索技术来查找一个键,而是用一个特殊的值,名为“散列码”。散列码可以获取对象中的信息,然后将其转换成那个对象“相对唯一”的整数(int)。所有对象都有一个散列码,而hashCode()是根类Object的一个方法。Hashtable获取对象的hashCode(),然后用它快速查找键。这样可使性能得到大幅度提升
(④)。散列表的具体工作原理已超出了本书的范围
(⑤)——大家只需要知道散列表是一种快速的“字典”(Dictionary)即可,而字典是一种非常有用的工具。

未完待续

新集合collection set list map

敬请期待java容器学习心得 (二)

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值