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); }