写的很好,还有自己的分析比较。推荐为参考答案。满分!
- package cn.itcast.heima;
- import java.util.AbstractSet;
- import java.util.Collection;
- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.Set;
- /*
- * 题目:
- * 通过查看源码、百度等多种手段学习并理解JavaSE中String、StringBuilder、ArrayList、HashSet等底层数据结构。
- * 要求将每个底层数据结构整理成一段文字并提交(对每个数据结构都能说出详细的原理则可获取满分)。
- *
- */
- public class JavaConstructorDemo {
- public static void main(String[] args) {
- //各个类的底层结构见方法体
- StringDemo();
- StringBuilderDemo();
- ArrayListDemo();
- HashSetDemo();
- }
- private static void StringDemo() {
- /* String类是java.lang包中的方法,直接继承Object类,它所实现的接口有Serializable, CharSequence, Comparable<String>
- * public final class String extends Object implements Serializable, Comparable<String>, CharSequence
- * String类代表字符串,不可被继承。Java中所有的字符串面值都作为此类的实例实现。
- * 字符串是常量,它们的值在创建之后不能更改。字符串缓冲区支持可变的字符串。因为String对象是不可变的,所以可以共享。
- * String类型是可序列化的,可比较的字符序列。
- * String.class中的序列号如下private static final long serialVersionUID = -6849794470754667710L;
- * 再看一下String类中定义的几个基本field
- *
- private final char value[]; String的值,String的本质就是char型数组
- private final int offset; 子数组第一个字符的索引
-
- private final int count; 字符串中的字符数量
- private int hash; 对象的hash code
- *
- * 经过上面的分析,其实我们已经能看出String对象的本质是一个经过封装的char型数组,封装后提供了一些方便操作的方法。
- */
-
- }
- private static void StringBuilderDemo() {
- /*
- * java.lang.StringBuilder
- * public final class StringBuilder extends AbstractStringBuilder
- * implements Serializable, CharSequence
- * StringBuilder继承Object类,不能被继承,与String相比没有实现Comparable接口。
- * StringBuilder是一个可变字符序列。一个类似于String的字符串缓冲区,不能被修改,
- * 但通过默写方法调用可以改变该序列的长度和内容,与StringBuffer相比StringBuilder不同步,
- * 在大多数视线中比StringBuffer要快。
- * StringBuilder.class中的构造函数构造了一个不带字符的字符缓冲区,初始容量为16个字符
- * public StringBuilder() {
- super(16);
- }
- * StringBuilder内部也是一个char数组,这和String内部的存储实现无异,但是StringBuilder的对象可变,与String相比
- * 不用每次创建新对象,效率高。
- *下面举例说明效率差别:
- *
- */
- String s = "";
- long begintime = System.currentTimeMillis();
- for (int i = 1; i <=10000; i++) {
- s+=i;
- }
- long endtime =System.currentTimeMillis();
- long time =endtime-begintime;
- System.out.println("String方法运行时间:"+time);
- //----------------------------------------
- StringBuilder s1 =new StringBuilder();
- s="";
- begintime =System.currentTimeMillis();
- for(int i =1;i<=10000;i++)
- {
- s=""+i;
- s1 = new StringBuilder(s);
- }
- endtime =System.currentTimeMillis();
- time = endtime-begintime;
- System.out.println("StringBuilder运行时间为:"+time);
-
- }
-
- private static void ArrayListDemo() {
- /*
- * public class ArrayList<E>extends AbstractList<E>
- * implements List<E>, RandomAccess, Cloneable, Serializable
- *ArrayList 继承了AbstractList,这个抽象类继承至AbstractCollection,AbstractCollection更像是实现List,Set共同的方法,
- *而AbstractSet、AbstractList更像是提供给Set、List各自特有方法的实现。
- *ArrayList是List接口的大小可变数组的实现。 允许包括null在内的所有元素,除了实现List接口外,此类还提供一些
- * 方法来操作内部用来出村列表的数组的大小,此方法是不同步的,ArrayList替代了Vector
- * 源码中
- private static final long serialVersionUID = 8683452581122892189L;
- 用于标识序列号
- * private transient Object elementData[];
- * 可以看到ArrayList就是一个数组
- * private int size;
- 该列表的大小,也就是元素个数。
- *public ArrayList(int initialCapacity) {
- super();
- if (initialCapacity < 0)
- throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);
- this.elementData = new Object[initialCapacity];
- }
- 构造函数,初始化内部数组为指定大小,列表是空的。
- * public ArrayList() {
- this(10);
- }
- 默认初始话内部数组大小为10
- ArrayList作为数组其查询速度很快 ,因为创建一个数组的时候 ,会在内存中分配一段
- 地址连续的空间,数组名就是这块内存空间的首地址。数组查询时直接找到对应数组名指向的内存空间首地址,
- 查询速度很快。如果根据内容查找Arraylist提供了一些遍历数组查找元素迭代方法 。
- 简单来说 ,ArrayList就是数组的一个封装类
-
- *
- */
-
- }
-
- private static void HashSetDemo() {
- /*
- * public class HashSet<E>
- extends AbstractSet<E>
- implements Set<E>, Cloneable, java.io.Serializable
- * HashSet继承AbstractSet,AbstractSet继承AbstractCollection这里不做重复。
- * 通过源码可以看出Set提供的方法和Collection指定的方法完全一样。具体区别要从
- * HashSet和TreeSet中体现。
- * private transient HashMap<E,Object> map;
- private static final Object PRESENT = new Object();
- * 从HashSet定义的属性可以看出HashSet底层是使用HashMap实现的,HashMap基于哈希表,
- * 存储键值对,key不能相同,保证了元素的不重复。PRESENT属性是一个Object对象,且是
- * static和final的,它的用途就是当做Value存进map中
- * 构造方法一:调用默认的HashMap构造方法初始化map
- * public HashSet() {
- map = new HashMap<E,Object>();
- }
- * 构造方法二:根据给定的Collection参数调用HashMap(int initialCapacity)的构造方法创建一个HashMap,
- * 调用addAll方法将c中的元素添加到HashSet对象中
- * public HashSet(Collection<? extends E> c) {
- map = new HashMap<E,Object>(Math.max((int) (c.size()/.75f) + 1, 16));
- addAll(c);
- }
- * 构造方法三:构造一个指定初始化容量和负载因子的HashMap
- public HashSet(int initialCapacity, float loadFactor) {
- map = new HashMap<E,Object>(initialCapacity, loadFactor);
- }
- * 构造方法四:构造一个指定初始化容量的HashMap
- public HashSet(int initialCapacity) {
- map = new HashMap<E,Object>(initialCapacity);
- }
- *构造方法五:构造一个指定初始化容量和负载因子的LinkedHashMap
- *dummy参数被忽略,只是用于区分其他的,包含一个int、float参数的构造方法
- HashSet(int initialCapacity, float loadFactor, boolean dummy) {
- map = new LinkedHashMap<E,Object>(initialCapacity, loadFactor);
- *
- * hash算法的功能:
- * 保证通过一个对象快速找到另一个对象;其算法价值体现在速度,可以保证查询快速执行;
- * 当从HashSet 中访问元素时,HashSet先计算该元素的hashCode(也就是该对象的hashCode方法返回值),
- * 然后直接到该HashCode对应的位置取出该元素; 在这里对象的hashCode就好比是数组里的索引,但是不是索引
- *
- * HashSet元素添加:
- * 当向HashSet集合中存入一个元素是,HashSet会调用该对象的HashCode()方法来得到该对象的hashCode值,
- * 判断已经存储在集合中的对象的hashCode值是否与添加的对象的hashCode值一致:若不一致,直接添加进去;
- * 若一致,再进行equals方法比较,equals方法如果返回true,表明对象已经添加进去了,就不会添加新的对象了,否则添加进去;
- * 如果我们重写了equals方法,也要重写hashCode方法,反之亦然。
- * HashSet集合判断连个元素相等的标准是两个对象通过equals方法比较相等,并且两个对象的hashCode方法返回值也相等。
- * 如果需要某个类的对象保存到HashSet集合中,覆写该类的equals()和hashCode()方法,应该尽量保证两个对象通过equals比较返回true时,他们的hashCode返回也相等。
- * 下例为HashSet功能实现
- *
- */
- Set s = new HashSet();
- s.add(new PersonDemo("王老吉"));
- s.add(new PersonDemo("王老吉"));
- s.add(new PersonDemo("王老吉"));
- System.out.println(s);
- }
- }
- class PersonDemo{
- private String name;
- public PersonDemo(String name){
- super();
- this.name= name;
- }
- public String toString(){
- return "name="+name;
- }
- public int hashCode(){
- final int prime= -31;
- int result =1;
- result = prime*result+((name==null)? 0:name.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj){
- if(this==obj)
- return true;
- if(obj ==null)
- return false;
- if(getClass()!=obj.getClass())
- return false;
- PersonDemo other = (PersonDemo)obj;
- if(name ==null){
- if(other.name!=null)
- return false;
- }else if(!name.equals(other.name))
- return false;
- return true;
-
- }
-
- }
复制代码 |