JAVA容器list、set

容器的思想 面向接口编程。

已经学习过数组Array,但是不可扩容,因此有了集合框架. 如果并不知道程序运行时会需要多少对象,或者需要

更复杂方式存储对象——可以使用Java集合框架

JUC: java util Concurrent 并发情况

接口Collection - 接口List - 实现类[ ArrayList , LinkedList (Vector 不常用)]

                     - 接口Set - 实现类[ HashSet , TreeSet ]  LinkedHashSet

接口Map - 实现类 [HashMap , TreeMap ]

Collections 提供了对集合进行排序、遍历等多种算法的实现.

Collection : 存放的是唯一的值

  特点:1、可以存放不同类型的数据,而数组只能存放固定类型的数据

     2、当使用ArrayList子类实现的时候,初始化长度为10,当长度不够时,会自动进行扩容操作.

  api方法:

     1、add : 要求必须传入的参数是Object对象,因此当写入基本数据类型的时候,包含了自动拆箱和自动装箱的过程.

List不Set接口
▪ Collection 接口存储一组丌唯一,无序的对象
▪ List 接口存储一组丌唯一,有序(插入顺序)的对象
▪ Set 接口存储一组唯一,无序的对象
▪ Map接口存储一组键值对象,提供key到value的映射
 
List接口的实现类
▪ ArrayList实现了长度可变的数组,在内存中分配连续的空间。
– 优点:遍历元素和随机访问元素的效率比较高
– 缺点:添加和删除需要大量移动元素效率低,按照内容查询效率低
▪ LinkedList采用链表存储方式。
– 优点:插入、删除元素时效率比较高
– 缺点:遍历和随机访问元素效率低下
▪ Vector  

* 1、Vector也是List接口的一个子类实现
* 2、Vector跟ArrayList一样,底层都是使用数组进行实现的
* 3、面试经常问区别:
* (1)ArrayList是线程不安全的,效率高,Vector是线程安全的效率低
* (2)ArrayList在进行扩容的时候,是扩容1.5倍,Vector扩容的时候扩容原来的2倍

Iterator 接口:
所有的集合都实现了Iterable的接口,实现此接口意味着具备了增强for循环的能力,也就是for - each
  增强for循环本质上使用的也是iterator的功能.所以增强for 多用.
  方法:iterator()    
     foreach()
在iterator的方法中,要求返回一个Iterator的接口子类实例对象,此接口包含了hasNext(), next(),
▪For-each循环
–增强的for循环,遍历array或Collection的时候相当简便
–无需获得集合和数组的长度,无需使用索引访问元素,无需循环条件
–遍历集合时底层调用Iterator完成操作
▪For-each缺陷
–数组:
▪不能方便的访问下标值
▪不要在for-each中尝试对变量赋值,只是一个临时变量
–集合:
▪不使用Iterator相比,不能方便 的删除集合中的内容
▪For-each总结
–除了简单的遍历并读出其中的内容外,不建议使用增强for
在迭代过程中,准备添加或者删除元素
ArrayList al=new ArrayList();
al.add("java1");//添加元素
al.add("java2");
al.add("java3");
//遍历
Iterator it=al.iterator();
while(it.hasNext()){
 Object obj=it.next();
 if (obj.equals("java2")) {
 al.add("java9");
 }
 System.out.println("obj="+obj);
}
ListIterator的作用解决并发操作异常
▪ 在迭代时,丌可能通过集合对象的方法(al.add(?))操作集合中的元素,
▪ 会发生并发修改异常。
▪ 所以,在迭代时只能通过迭代器的方法操作元素,但是Iterator的方法
▪ 是有限的,只能进行判断(hasNext),取出(next),删除(remove)的操作,
▪ 如果想要在迭代的过程中进行向集合中添加,修改元素等就需要使用
▪ ListIterator接口中的方法
ListIterator li=al.listIterator();
while(li.hasNext()){
 Object obj=li.next();
 if ("java2".equals(obj)) {
 li.add("java9994");
 li.set("java002");
 } }
Set接口
▪ Set接口
– Set接口存储一组唯一,无序的对象
– (存入和取出的顺序不一定一致)
– 操作数据的方法不List类似,Set接口不存在get()方法
--使用treeset底层实现的是treemap,利用红黑树实现
--设置元素的时候,如果是自定义对象会查找对象中的equals和hashcode方法,如果没有,比较的是地址。
--树中的元素是默认进行排序操作的,如果是基本类型,自动比较,如果是引用类型的话,需要自定义比较器
  --内部比较器:定义在元素的类中,通过实现comparable接口进行实现
  --外币比较器:定义在当前类中,通过实现comparator接口来实现,但是需要将该比较器传递到集合中.(
    TreeSet treeset = new TreeSet(new Demo());
  )  注意:外部比较器可以定义成一个工具类,此时所有需要比较的规则如果一致的话,可以复用;
                     内部比较器只有存储在当前对象的时候才可以使用
                     如果两种比较器同时存在,使用外部。
      当时用比较器的时候,不会调用equals方法。
 public static void main(String[] args) {
        Set set = new HashSet();
        set.add("123");
        set.add(1);
        set.add(true);
        set.add("123");
        System.out.println(set);
        Iterator iterator = set.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        System.out.println("----------------");
        //推荐使用这种方式,因为iter作用域在for内,垃圾回收
        for (Iterator iter = set.iterator();iter.hasNext();){
            System.out.println(iter.next());
        }
    }
▪HashSet:采用Hashtable哈希表存储结构
–优点:添加速度快,查询速度快,删除速度快
–缺点:无序
总结:
▪ HashSet是如何保证元素的唯一性的呢?
▪ 答:是通过元素的两个方法,hashCode和equals方法来完成
▪ 如果元素的HashCode值相同,才会判断equals是否为true
▪ 如果元素的hashCode值丌同,丌会调用equals方法
–LinkedHashSet
▪ 采用哈希表存储结构,同时使用链表维护次序
▪有序(添加顺序)
▪TreeSet    (类型必须一致).
–采用二叉树(红黑树)的存储结构,使用treeset底层实现的是treemap 
–优点:有序(排序后的升序)查询速度比List快
–缺点:查询速度没有HashSet快
        TreeSet treeSet = new TreeSet();
        treeSet.add(45);
        treeSet.add(5);
        treeSet.add(99);System.out.println(treeSet);

执行结果:[5, 45, 99]   //排序

Comparable 接口
TreeSet根据什么确定集合中对象的“大小”顺序?
• 所有可以“排序”的类都实现了java.lang.Comparable 接口,
Comparable接口中只有一个方法
public int compareTo(Object obj);
该方法:
返回 0 表示 this == obj
 返回正数 表示 this > obj
 返回负数 表示 this < obj
实现了Comparable 接口的类通过实现 comparaTo 方法从而确定该类对象的排序方式。public class StrLenComparator implements Comparator<String> {

public class StrLenComparator implements Comparator<String> {
@Override
public int compare(String o1, String o2) {
  if (o1.length()>o2.length()) {
    return 1;
  }
  if (o1.length()<o2.length()) {
    return -1;
  }
  return o1.compareTo(o2);//长度相同,按字母
  } 
}
public static void sortDemo(){ List<String> list=new ArrayList<String>(); ..添加元素 sop(list); Collections.sort(list);//按字母排序 sop(list); //按照字符串长度排序 Collections.sort(list,new StrLenComparator()); sop(list); }

 

posted @ 2022-10-17 21:45  宝宝佩恩天道  阅读(40)  评论(0编辑  收藏  举报