day12-笔记

  
一:集合的特点:
    长度可变
    对象持久化 集合里面存储的是对象的地址
集合分类:
    Collection:单列
              List:    有顺序 可以重复
                  Vector: 线程安全的ArrayList, 效率略低  现已很少用了
                   ArrayList: 底层用数组实现  查找块 ,增删慢
               自己定义的一个ArrayList
public class MyArrayList {
 private Object[] data = new Object[10];
 private int size;
 public void add(Object obj) {
  if (size == data.length) { // size如果等于数组长度, 说明数组中装满了.
   Object[] newData = new Object[data.length * 3 / 2 + 1]; // 创建一个更大的新数组, 增加一半多一个
   System.arraycopy(data, 0, newData, 0, data.length); // 将原数组中的内容拷贝到新数组
   data = newData; // 记住新的数组
  }
  data[size++] = obj;
 }
 public Object get(int index) {
  checkRange(index);
  return data[index];
 }
 public int size() {
  return size;
 }
 public void remove(int index) {
  checkRange(index);
  System.arraycopy(data, index + 1, data, index, --size - index);
  data[size] = null;
 }
 public void checkRange(int index) {
  if (index >= size) // 如果要获取的索引大于等于size, 说明越界, 抛出异常
   throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
 }
 public Iterator iterator() {
  return new Iterator() { // 先写一个Iterator类的子类, 再使用这个类创建一个对象返回.
   private int pos = -1;

   public boolean hasNext() {
    return data[pos + 1] != null; // 如果当前位置的下一个不为空, 就返回true, 否则返回false
   }

   public Object next() {
    return data[++pos]; // 获取下一个元素
   }

   public void remove() {
    MyArrayList.this.remove(pos--); // 删除当前位置, 再将当前位置向前移动一位.
   }

  };
 }
}
                   LinkedList :底层用链表 实现, 增删块 , 查找慢   因为太麻烦 改天写 
                     
二.List
 1.ArrayList
  ArrayList是数组实现.
  查找时是直接获取数组中元素, 所以效率非常高.
  在增加元素时, 有可能超出数组长度, 这时要创建新数组, 并且复制原有元素, 所以效率低.  
  在删除元素时, 因为需要将后面的元素拷贝, 所以效率也比较低.
 2.删除List集合中的元素
  由于删除元素后, 后面的所有元素都会向前移动一位.
  所以在删除的时候需要注意, 如果使用for循环形式删除, 那么需要在删除之后, 将循环变量减1.
  或者可以使用Iterator中的remove()方法
 3.LinkedList
  LinkedList是链表实现.
  增加元素的时候只要让集合中最后一个元素记住它的下一个元素是当前元素, 让当前元素记住前一个是刚才的最后一个. 这样做效率较高.
  删除时只要让前一个记住后一个, 让后一个记住前一个. 这样效率也很高.
  而查找时需要逐个去找, 这时效率就较低了
  
三.JDK5新特性
 1.泛型
  在给集合类加上泛型之后, 集合类中就只能存放同一类型的元素了.
  这样做的好处是:
   将运行期容易发生的错误转到了编译期
   省去了类型强转的麻烦
 2.增强for循环
  只要实现了Iterable接口的子类, 都可以使用增强for循环来遍历.
  增强for循环就是调用了该类的iterator()方法, 获取其对应的Iterator, 使用Iterator的hasNext()和next()方法来完成遍历的.
  增强for循环的语法: for(元素类型 变量名 : 要遍历的容器) 例如: for (Person p : list)
  在增强for循环中不能删除元素
  
  
四.Set
 1.Set的特点
  和List一样, 都是Collection的子类. 但没有存储顺序, 不允许重复.
 2.HashSet
  HashSet在存储对象的时候, 会先通过hashCode()方法计算哈希值, 然后再调用equals()方法比较. 目的就是先用hashCode分类, 降低equals的次数.
  hashCode()是通过对象的属性来计算的, 如果对象的所有属性相同, 哈希值相同. 属性值不相同, 哈希值也有可能相同.
  HashSet在存储一个对象的时候, 会先调用该对象的hashCode()方法计算一个哈希值(相当于分类).
  在集合中看有没有和这个对象哈希值相同的对象.
   如果没有哈希值相同的对象, 那么肯定就没有相同的对象, 直接存入.
   如果有哈希值相同的对象, 再和那些哈希值相同的对象进行equals()比较.
    如果比较结果是true, 则是相同, 不存. 如果比较结果是false, 那么就是不同对象, 存入.
  如果想将一个类的对象存入HashSet让HashSet去掉重复元素, 那么我们就要重写这个对象的hashCode和equals方法
 3.TreeSet
  以二叉树形式存储, 没有重复元素, 并且有逻辑顺序.
  在使用TreeSet存储对象时, 需要指定比较的算法, 指定的方式有两种:
   自然顺序: 使用该对象的compareTo方法进行比较
   比较器: 在TreeSet的构造函数中传入一个Comparator的子类, 其中重写compare方法, TreeSet在添加对象时就会使用比较器的比较方法了
  如果一个类有自然顺序, 而TreeSet的构造函数中也传入了比较器, 那么会优先比较器.
  因为如果优先自然顺序, 那么多个TreeSet只能用相同的算法排序, 而优先比较器, 在不同的TreeSet中只要传入不同的比较器, 就可以按不同的算法排序.
public int hashCode() {
  final int prime = 31; // 素数, 质数
  int result = 1;
  result = prime * result + age;
  result = prime * result + ((name == null) ? 0 : name.hashCode());
  return result; // 只要属性相同, 那么算出的结果就相同, 而且让这个值保持在一个范围之内.
 }

 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (getClass() != obj.getClass())
   return false;
  final Person other = (Person) obj;
  if (age != other.age)
   return false;
  if (name == null) {
   if (other.name != null)
    return false;
  } else if (!name.equals(other.name))
   return false;
  return true;
 }

 // 此方法返回一个int值, 正数, 负数, 或0
 public int compareTo(Person o) {
  int ageGap = this.age - o.age; // 计算年龄的差值
  return ageGap != 0 ? ageGap : this.name.compareTo(o.name); // 如果年龄不同, 直接返回年龄差值, 如果年龄相同, 返回名字差值
 }

public class TreeSetDemo {

 public static void main(String[] args) {
  TreeSet<Person> set = new TreeSet<Person>(new Comparator<Person>() { // 在TreeSet的构造函数中传入一个Compartor, 重写compare方法指定比较算法
     public int compare(Person p1, Person p2) {
      int nameGap = p1.getName().compareTo(p2.getName());
      return nameGap != 0 ? nameGap : p1.getAge() - p2.getAge();
     }
    });

  set.add(new Person("zs", 21)); // 第一个对象肯定可以存
  set.add(new Person("ls", 22)); // 将第二个对象强转为Comparable, 调用其compareTo方法和前一个对象比较. 如果是负数存左边, 如果是正数存右边, 0就不存.
  set.add(new Person("ww", 20));
  set.add(new Person("zl", 19));
  set.add(new Person("sq", 21));
  set.add(new Person("zb", 21));
  set.add(new Person("zb", 21));
  set.add(new Person("zb", 20));

  for (Person p : set)
   System.out.println(p);
  

  // 默认比较方式是自然顺序, 也就是对象实现Comparable之后的compareTo方法返回的顺序
 }

}
  
五.重点
 1.自定义一个类, 定义一个HashSet, 使用自定义类创建N个对象放入HashSet, 做到去重复.
 2.自定义一个类, 定义一个TreeSet, 使用类创建对象, 装入TreeSet, 可以使用TreeSet排序. 用两种方式实现(自然顺序, 比较器)
 3.Set集合两种遍历方式, 增强for循环, 迭代器Iterator.
 4.List集合四种遍历方式, for循环, 迭代器, 枚举Enumeration, 增强for循环
 5.List和Set的区别和共同点: 都是单列集合, 都是Collection的子类. List是有存储顺序, 可重复, Set是无存储顺序, 不可重复.
 6.List集合中的ArrayList,LinkedList,Vector之间的区别:
  ArrayList和Vector都是数组实现, 查找快, 增删慢. Vector是线程安全, 效率略低于ArrayList.
  LinkedList是链表实现, 增删快, 查找慢.
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值