# 集合存储结构
**集合和数组的区别**
**1. 数组能容纳基本数据类型和引用数据类型;集合只接收引用数据类型。
2. 数组的长度是固定的。【集合长度可变的。】
3. 数组可进行的操作很有限:
4. 集合是对象,有方法和属性可供调用,功能丰富了;面向对象的特性,封装,继承,多态。**
## 1.Collection接口
Collection接口中的方法
add(Objectionn o)添加一个元素
size() 元素的个数
addAll(Collection extends E> c) 添加一个集合对象的元素
contains(Object o) 是否包含该"o"元素
isEmpty() 是否为空
iterator() 迭代
remove(Object o) 删除对象
toArray() 返回数组
## 2. List接口
List集合中的元素都是有序可重复的集合
List接口中的方法
void add(int index, Object ele) //指定下标添加元素
boolean addAll(int index, Collection eles) //指定下标添加集合
Object get(int index) //获取下标的元素
int indexOf(Object obj) //从左到右获取元素的下标
int lastIndexOf(Object obj) //从右到左获取元素的下标(永远从0开始的)
Object remove(int index) //通过下标删除
Object set(int index, Object ele) //修改下标的元素
List subList(int fromIndex, int toIndex) //返回一个子集合(不包含toIndex下标)
**2.1、ArrayList**
有序,不唯一;有序是索引顺序;
*(1)遍历时按添加顺序;
*(2)内存原理:内存中分配的是连续的空间;有索引,
* ArrayList是一个Object类型的数组;数组长度不够了,会生成更长的新数组;
*(3)性能:按索引查询,效率高;
* 按内容查询,效率低;
* 添加删除元素效率低;可能引起大量元素的位移;
/*
*ArrayList的遍历方法:
*1.for-each;
*2.普通for循环;操作索引;
*3.迭代器:
* 1)生成迭代器:Iterator it=list.iterator();//it初始位置在索引为0的元素之前;
* 2)it.hasNext():以it当前位置为参照,还有下一个元素吗?
* 3) it.next():先把it当前位置的下一个元素取出来;把it的位置往后移动一个元素;
* 4)it.remove():把it当前位置的元素删除。
* 5)在用迭代器遍历集合期间,不要用集合对象名对集合进行操作(如list.add(6)),会出现并发修改异常:java.util.ConcurrentModificationException。
```
public class Test2 {
public static void main(String[] args) {
List list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
// 集合的遍历;for-each;
// for (Object obj : list) {
// System.out.println(obj.toString());
// }
//普通的for循环;
// for(int i=0;i // Object obj=list.get(i); // System.out.println(obj); // } Iterator it=list.iterator(); while(it.hasNext()){ Object obj=it.next();//把it原有位置的下一个元素取出来;把it的位置往后移动一个元素; System.out.println(obj); //list.add(6);会出现并发修改异常:java.util.ConcurrentModificationException。 it.remove();//it指向的是哪个元素,就删除哪个元素; } System.out.println(list.size()); } } ``` **2.2 LinkList** .链表:LinkedList,物理空间上不连续,但逻辑上是连续的。 添加删除元素效率高;不会引起大量元素的位移; *LinkedList的特点:有序,不唯一;有序是索引顺序; *(1)遍历时按添加顺序; *(2)内存原理:链表 *(3)性能:按索引查询,效率低;必须从第一个元素查起; * 按内容查询,效率低; * 添加删除元素效率高;不会引起大量元素的位移; 1.for-each; 2.普通for循环;操作索引; 3.迭代器: ``` public class Test { public static void main(String[] args) { // 创建一个容器对象; List list = new LinkedList();// 运用多态; List subList = new LinkedList(); subList.add(1); subList.add(2); // 添加; Person p1 = new Person(); Person p2 = new Person(); // add(Object obj):Object做形参,可以接收不同的子类实参;运用多态; list.add(p1); list.add(p2); list.add("Hello"); // 123--->Object obj=new Integer(123);添加数字相当于自动装箱; list.add(123); list.add(2, "java"); list.addAll(subList); list.addAll(2, subList); // 删除; // list.remove(2);//2是索引位置; // list.remove("java");//如果有多个"java",就删除第一个; // list.remove(new Integer(2)); // list.removeAll(subList);//删除的是所有和subList里相同的元素,删除的是与subList的交集; // 改; list.set(1, "today is perfect"); // list.clear(); //list.retainAll(subList);// 取与subList交集; // 查; System.out.println(list.size());// 实际元素的个数,不是集合的总容量; // System.out.println(list.get(0));//得到索引为0的位置的元素; System.out.println(list.contains(p1)); System.out.println(list.isEmpty()); // 集合的遍历; for (Object obj : list) { System.out.println(obj.toString()); } // 普通的for循环; for (int i = 0; i < list.size(); i++) { Object obj = list.get(i); System.out.println(obj); } Iterator it = list.iterator(); while (it.hasNext()) { Object obj = it.next();// 把it原有位置的下一个元素取出来;把it的位置往后移动一个元素; System.out.println(obj); // list.add(6);会出现并发修改异常:java.util.ConcurrentModificationException。 it.remove();// it指向的是哪个元素,就删除哪个元素; } System.out.println(list.size()); } } ``` ## 3.Set接口 Set接口 元素无序(hashCode())、不可重复的集合 HashSet LinkedHashSet TreeSet 1)HashSet 无序(hashCode())、不可重复的集合 hashCode() equals() *HashSet的特点:无序,唯一; *(1)遍历是不可预知顺序; *(2)内存原理:哈希表,用hashcode和equals()方法; *(3)性能:查询效率高; * 添加删除效率高; *(4)自定义类,建议重写hashcode()和equals()方法,成对重写。 * 告诉程序你的比较策略。 * 不重写,就用Object的方法了。 1. HashSet怎么保证元素的唯一性呢? *先用hashcode计算出地址,如果没有元素,就存进去;如果已有元素,就用equals(),如果true,不添加了; *如果false,就添加。 * *hashcode相同,元素不一定相同;再用equals(),true才是相同的。 *hashcode不同,元素一定不同。 2.遍历: * 1)for-each: * 2)迭代器:Iterator it=set.iterator(); * *3.添加: * set.add(Object obj); * set.addAll(); * * 删除: * set.remove(Object obj); * set.removeAll(); * * 查: * set.isEmpty(); * set.size(); * set.clear(); * set.contains(); * set.containsAll(); * set.retainAll(); * * 转换: * //把集合类型转成Object类型的数组; Object[] objArr=set.toArray(); * * */ ``` public class TestHashSet { public static void main(String[] args) { //创建一个HashSet对象; Set set=new HashSet(); //添加; System.out.println(set.add(23));//true; set.add(36); set.add(48); set.add(77); set.add(86); set.add(67); set.add(76); System.out.println(set.add(23));//false; set.add(56); set.add(78); set.add(47); //删除; set.remove(47); //改; //查; System.out.println(set.size()); System.out.println(set.isEmpty()); //set.clear(); //遍历; Iterator it=set.iterator(); while(it.hasNext()){ Object obj=it.next(); System.out.println(obj); } System.out.println("=========================="); //用for-each遍历; for(Object obj:set){ System.out.println(obj.toString()); } //把集合类型转成Object类型的数组; Object[] objArr=set.toArray(); System.out.println(Arrays.toString(objArr)); } } ``` 2)LinkedHashSet:遍历输出的内容和添加的顺序一致 3)TreeSet * 1.添加元素必须是同一类型,否则遍历出错 * 2.遍历输出顺序按默认顺序(从小到大)如:String,Integer等 * 3.自然排序,必须要实现Comparable,compareTo方法,实现排序 * 4.定制排序,需要实现接口Comparator接口 *TreeSet:有序,唯一;有序,不是添加顺序,是大小顺序; *(1)遍历时是大小顺序; *(2)内存原理:二叉树; *(3)查询(按内容查询),效率中等;在ArrayList和HashSet之间; * 添加删除,效率中等。 *(4)如果是自定义类,要实现Comparable接口; * 告诉程序你的比较策略; * 否则会报:java.lang.ClassCastException:Student--->Comparable; * * Set treeSet=new TreeSet(); * *(5) 也可以实现Comparator接口; ``` * StuScoreComp sComp=new StuScoreComp(); Set treeSet = new TreeSet(sComp); public class TestTreeSet { public static void main(String[] args) { //创建TreeSet对象; Set treeSet=new TreeSet(); //添加; treeSet.add(50); treeSet.add(35); treeSet.add(78); treeSet.add(27); treeSet.add(45); treeSet.add(56); treeSet.add(40); treeSet.add(45); treeSet.add(48); treeSet.add(90); //遍历; Iterator it=treeSet.iterator(); while(it.hasNext()){ Object obj=it.next(); System.out.println(obj); } } } ``` ## 4.Map接口 *Map特有的三个方法: *map.keySet();获取key的集合; *map.values();获取value的集合; *map.entrySet();获取key和value的集合; Map接口 key-value对”的集合 HashMap(效率高) LinkedHashMap TreeMap HashTable(古老的类,基于线程安全,效率低) Properties load(InputStream inStream) 从输入字节流读取属性列表(键和元素对)。 *HashMap: *1.是键值对,每个元素包含两部分:key,value; *2.key和value是一一对应的; *3.key是无序,唯一的;如果添加了重复的key,不报错,后面的会覆盖前面的; *4.value是无序,不唯一的; *5.key和value都可以是null。 *6.如果key是自定义类:要重写hashCode()和equals()方法; * 告诉程序你的比较策略; 内存原理:key部分与HashSet原理相同,无序,唯一; 事实上,HashSet底层调用的是HashMap. /* *HashMap底层是一个Entry类型的数组; *Entry *Entry:key,value和指向下一个Entry元素的引用。 * * ``` */ public class TestHashMap1 { public static void main(String[] args) { Map map.put(1, "罗马假日"); map.put(3, "三国演义"); map.put(2, "炼金术士"); //遍历: Set entrySet=map.entrySet(); Iterator while(it.hasNext()){ // it.next().getKey(); // it.next().getValue(); Entry entry=it.next(); System.out.println(entry); } } } ``` /* *TreeMap: 有序(大小顺序),唯一;按key排序; *如果key是自定义类:要实现Comparable或Comparator接口; *告诉程序你的比较策略; * */ ``` import java.util.TreeMap; public class TestTreeMap { public static void main(String[] args) { Map map.put(16, "炼金术士"); map.put(2, "炼金术士"); map.put(1, "罗马假日"); map.put(3, "三国演义"); map.put(2, "围城"); //遍历: Set entrySet=map.entrySet(); Iterator while(it.hasNext()){ Entry entry=it.next(); System.out.println(entry); } } } ``` ## 5.迭代器 迭代器: * 1)生成迭代器:Iterator it=list.iterator();//it初始位置在索引为0的元素之前; * 2)it.hasNext():以it当前位置为参照,还有下一个元素吗? * 3) it.next():先把it当前位置的下一个元素取出来;把it的位置往后移动一个元素; * 4)it.remove():把it当前位置的元素删除。 * 5)在用迭代器遍历集合期间,不要用集合对象名对集合进行操作(如list.add(6)),会出现并发修改异常:java.util.ConcurrentModificationException。 list.iterator(): (1) iterator()不是Collection自己的方法,是继承自接口Iterable; (2) Iterator iterator();返回值是Iterator类型的; (3) Iterator: 是一个接口类型,它里面的三个方法:hasNext(); next(); remove(); (4)遍历[集合]时底层调用Iterator完成操作。 ## 6.Collectiongons工具类 /* *1.Collections: * 1)和Arrays一样,是专门用来操作集合的工具类; * 2)大部分方法 都是静态的,可以通过类名直接调用; * 3)构造方法私有化,不能创建Collections的对象; * *2.Collections的常用方法: * 1)Collections.addAll(list,60,50); * //如果是自定义对象,要给出比较策略,实现Comparable接口; * 2)Collections.sort(list); * //用于排好序的集合上;查到就返回索引值,没查到就返回-(应该在的位置+1); * 3)int index=Collections.binarySearch(list, 67); * 4)Collections.copy(list, list2); * 5)int max=Collections.max(list); 6)int min=Collections.min(list); 7)Collections.fill(list, 888); 8)Collections.reverse(list); * 9)List list3 = Collections.synchronizedList(list); * *3.Collection和Collections的区别: * 1)Collection是Java提供的集合接口,存储一组不唯一,无序的对象。它有两个子接口List和Set。 2)Java中还有一个Collections类,专门用来操作集合类 ,它提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。 */ ``` public class TestCollections { public static void main(String[] args) { ArrayList list=new ArrayList(); //添加Integer类型的元素; list.add(3); list.add(4); list.add(1); list.add(2); list.add(5); Collections.addAll(list,60,50); //Collections.sort(list); //int index=Collections.binarySearch(list, 50); ArrayList list2=new ArrayList(); Collections.addAll(list2,11,12,13,14); Collections.copy(list, list2); //Collections.fill(list, 888); //Collections.reverse(list); int max=Collections.max(list); int min=Collections.min(list); System.out.println(max+" "+min); //System.out.println(index); //遍历: Iterator it = list.iterator(); while (it.hasNext()) { System.out.println(it.next()); } //ArrayList是线程非同步,程序员可以自己写代码把ArrayList转成同步的操作; List list3 = Collections.synchronizedList(list); } } ```