引入 数组存储的特点
数组一旦初始化,长度就确定了
数组中的多个元素是依次紧密排列的,有序的,可重复的。
数组一旦初始化完成,其元素的类型就是确定的。不是此类型的,就不能添加到此数组中
元素的类型可以是基本数据类型,也可以是引用数据类型
反向来看 :
一旦初始化,长度就不可变了
数组中存储元素特点的单一性。对于无须、不可重复的场景的多个数据就无能为力了
数组中可用的方法、属性都很少。具体需要都需要自己来组织相关代码逻辑
对于数组中元素的删除、插入操作,性能较差。
Java集合框架体系 1.java.util.Collection :存储一个个的数据
子接口:List: 存储有序的、可重复的数据
**ArrayList(主要)**、LinkedList、Vector
子接口:**Set:**存储无序的、不可重复的接口
**HashSet(主要)**、LinkedHashSet、TreeSet
2**.java.util.Map:**存储一对一对的数据
**HashMap(主要)**、LinkedHashmap、TreeMap、Hashtable、Properties
Collection 常用方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 @Test public void test1 () { Collection coll = new ArrayList (); coll.add("aaa" ); coll.add(123 ); coll.add(new Object ()); System.out.println(coll); Collection coll1 = new ArrayList (); coll1.add("bbb" ); coll1.add("fff" ); System.out.println(coll.size()); coll.addAll(coll1); System.out.println(coll); System.out.println(coll.isEmpty()); System.out.println(coll.contains("aaa" )); Collection coll3 = new ArrayList (); coll3.add("xx" ); coll3.add("haha" ); System.out.println(coll.containsAll(coll3)); Object[] arr = coll.toArray(); System.out.println(Arrays.toString(arr)); String[] arr2 = new String []{"aa" ,"bb" }; Collection list = Arrays.asList(arr2); System.out.println(list); }
添加元素的要求:
要求元素所属的类一定要重写equals()
迭代器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Test public void test () { Collection coll = new ArrayList (); coll.add("aaa" ); coll.add(123 ); coll.add(new Object ()); Iterator iterator = coll.iterator(); System.out.println(iterator.next()); System.out.println(iterator.next()); System.out.println(iterator.next()); while (iterator.hasNext()){ System.out.println(iterator.next()); } }
foreach循环 格式:
for(要遍历的集合或数组元素的类型 临时变量: 要遍历的集合或数组变量){
操作临时变量的输出
}
针对于集合来讲,增强for循环的底层仍然使用的是迭代器
增强for循环的执行过程中,是将集合或数组中的元素一次赋值给临时变量,注意循环体中对临时变量的修改,可能不会导致原有集合或数组中元素的修改。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Test public void test2 () { Collection coll = new ArrayList (); coll.add("aaa" ); coll.add(123 ); coll.add(new Object ()); for (Object obj : coll) { System.out.println(obj); } int [] arr = new int []{1 ,2 ,3 ,4 ,5 }; for (Object i : arr) { System.out.println(i); } }
List(Collection) 常用方法 1.collections中含有的15个方法
2.由于集合是有序的,进而就有与索引相关的一些方法
插入元素:
void add(int index, Object ele)
boolean addAll(int index, Collection eles)
获取元素
Object get(int index):获取指定index位置的元素
List subList(int fromIndex, int toIndex)返回从fromIndex到toIndex的位置的子集合
获取元素索引
int indexOf(Object obj):返回obj在集合中首次出现的位置
int lastIndexOf(Object obj):返回Obj在当前集合中末次出现的位置
删除和替换元素
Object remove(int index):移除指定index位置的元素,并返回此元素
Object set(int index, Object ele):设置指定index位置的元素为ele
小结:
增 :add(Object obj) addAll(Collection coll)
删 : remove(Object obj) remove(int index)
改 :set(int index, Object ele)
查 :get(int index)
插 :add(int index, Object ele) addAll(int index, Collection eles)
长度 : size()
遍历 :iterator(), foreach, for
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Test public void test1 () { List list = new ArrayList (); list.add("AA" ); list.add(123 ); list.add("bb" ); System.out.println(list.toString()); list.add(2 ,"Cc" ); List list1 = Arrays.asList(1 ,2 ,3 ); list.addAll(1 ,list1); System.out.println(list); list.remove(2 ); list.remove(Integer.valueOf(2 )); }
实现类及其特点 ArrayList: List的主要实现类:线程不安全、效率高;底层使用Object[]数组存储。添加、查询数据时效率高;插入、删除时,效率较低
LinkedList: 底层使用双向链表进行存储。在对集合中的数据频繁进行删除和插入时建议使用此类。插入、删除时,效率高,添加、查询数据时效率低。
Vector:List的古老实现类:线程安全、效率低;底层使用Object存储数据
Set(Collection) 无序性、不可重复性的理解 无序性 : 不是随机性。也不是添加元素的顺序和遍历元素的顺序的不一致。而是与添加元素位置有关,不像ArrayList一样是依次紧密排列的,而是根据添加元素的哈希值,计算的其在数组中存储的位置。此位置不是依次排列的,表现为无序性
不可重复性 :添加到Set中的元素是不能相同的。比较的标准,需要判断hashCode()得到的哈希值与equals()得到的结果。
常用方法: 即为Collection中声明的15个抽象方法。没有新增的方法
开发场景 较List、Map来说,set使用的频率较少
实现类: **HashSet:**主要实现类;底层使用HashMap,即使用数组+单向链表+红黑树结构进行存储
LinkedHashSet: 是HashSet的子类。在现有数组+单向链表+红黑结构基础上,又添加了一组双向链表,用于记录添加元素的先后顺序。即:我们可以按照添加元素的顺序实现遍历。便于频繁的查询操作。
TreeSet :底层使用红黑树存储。可以按照添加的元素的指定的属性的大小顺序进行遍历
添加到HashSet/LinkedHashSet中元素的要求: 要求元素所在的类要重写两个方法:equals()和hashCode().
同时要求equals()和hashCode()要保持一致性
TreeSet 向TreeSet中添加元素的要求
添加到TreeSet中的元素必须是同一个类型的对象,否则会报ClassCastException.
判断数据是否相同的标准:
不再是考虑hashCode()和equals()方法了,也就意味着添加到TreeSet中的元素不再需要重新hashcode和equals()
比较元素大小的或比较元素是否相等的标准就是考虑自然排序或定制排序中compareTo()或compare()的返回值。如果compareTo()或compare()的返回值为0,则认为两个对象是相等的。由于TreeSet中不能存放相同的元素,则后一个相等的元素就不能添加到TreeSet中。
Map 实现类及对比
HashMap:主要实现类;线程不安全,效率高;可以添加null的key和value的值;底层使用数组+单向链表+红黑树结构存储
LinkedHashMap:是HashMap的子类,在HashMap使用的结构基础上,增加了一对双向链表,用于记录添加的元素的先后顺序。遍历的时候可以按照添加的顺序显示。开发中,对于频繁的遍历操作,建议使用此类。
Hashtable:古老实现类;线程安全,效率低;不可以添加null的key和value值;底层使用数组+单向链表结构存储
TreeMap:底层使用红黑树存储;可以安装添加的key-value中key元素的指定的属性的大小顺序进行遍历。需要考虑1.自然排序 2.定制排序
Properties:其key和value都是String类型。常用来处理属性文件。
HashMap中元素的特点
HashMap中的所有的key彼此之间是不可以重复的、无序的。所有的key就构成了一个Set 集合。 ==》key 所在的类要重写hashCode()和 equals()
HashMap中的所有的value彼此之间是可重复的、无序的。所有的value就构成一个Collection 集合。==》value 所在的类要重写equals()
HashMap中的一个key-value就构成了一个Entry。
HashMap中所有的entry彼此之间是不可重复的、无序的。所有的entry就构成了一个set集合。
常用方法 添加、修改操作:
Object put(Object key, Object value):将指定key-value添加到当前map对象中
void putAll(Map m):将m中所有key-value对存放到当前map中
删除
Object remove(Object key) 移除指定key的key-value对,并返回value
void clear():清空当前map中所有的数据
元素查询
Object get(object key)获取指定key对应value
boolean containKey(Object key)是否包含指定的key
boolean containsValue(Object value):是否包含指定的value
int size():返回map中key-value对的个数
boolean isEmpty():判断当前map是否为空
boolean equals(Object obj):判断当前map和参数对象是否相等
元视图操作的方法
Set keySet() 返回所有key构成的Set集合
Collection values():返回所有value构成的Collection集合
Set entrySet():返回所有key-value对构成的Set集合
小结:
增:put(Object key, Object value), putAll(Map m)
删:Object remove(Object key)
改:put(Object key, Object value), putAll(Map m)
查:Object get(Object key)
长度:size()
遍历:
遍历key集: Set keySet()
遍历value集: Collection values()
遍历entry集:Set entrySet()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 @Test public void test1 () { HashMap map = new HashMap (); map.put("AA" , 56 ); map.put(65 ,"TOM" ); map.put("BB" , 78 ); System.out.println(map); System.out.println(map.size()); Object value = map.remove("AA" ); System.out.println(map); Object oldValue = map.put("BB" ,99 ); System.out.println(oldValue); System.out.println(map); Object value1 = map.get("BB" ); System.out.println(value1); Set keySet = map.keySet(); Iterator iterator = keySet.iterator(); while (iterator.hasNext()){ Object key = iterator.next(); System.out.println(key); } Collection values = map.values(); for (Object obj: values){ System.out.println(obj); } Set keySet1 = map.keySet(); for (Object key:keySet1){ Object value2 = map.get(key); System.out.println(value2); } Set entryset = map.entrySet(); Iterator iterator2 = entryset.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); Map.Entry entry = (Map.Entry) iterator2.next(); System.out.println(entry.getKey()+"-->" +entry.getValue()); } Set keySet2 = map.keySet(); for (Object key:keySet2){ System.out.println(key+ "--->" +map.get(key)); } } }
TreeMap的使用
底层使用红黑树存储
可以按照添加的key-value的key元素指定的属性大小顺序进行遍历
需要考虑1.自然排序 2.定制排序
要求向TreeMap中添加的key必须是同一个类型的对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 public class TreeMapTest { @Test public void test1 () { TreeMap map = new TreeMap (); map.put("CC" , 89 ); map.put("BB" ,78 ); map.put("jj" ,new Data ()); map.put("kk" ,78 ); Set entrySet = map.entrySet(); for (Object entry:entrySet){ System.out.println(entry); } } @Test public void test2 () { TreeMap map = new TreeMap (); User u1 = new User ("Tom" , 23 ); User u2 = new User ("Jerry" ,43 ); User u3 = new User ("Rose" ,13 ); User u4 = new User ("Jack" ,23 ); User u5 = new User ("Tony" , 33 ); map.put(u1,78 ); map.put(u2,76 ); map.put(u3,76 ); map.put(u4,77 ); map.put(u5,45 ); Set entrySet = map.entrySet(); for (Object entry:entrySet){ System.out.println(entry); } } @Test public void test3 () { Comparator comparator = new Comparator () { @Override public int compare (Object o1, Object o2) { if (o1 instanceof User && o2 instanceof User) { User u1 = (User) o1; User u2 = (User) o2; int value = u1.getName().compareTo(u2.getName()); if (value != 0 ) { return value; } return u1.getAge() - u2.getAge(); } throw new RuntimeException ("类型不匹配" ); } }; TreeMap map1 = new TreeMap (); } } class User implements Comparable { private String name; private int age; public User () { } public User (String name, int age) { this .name = name; this .age = age; } public String getName () { return name; } public void setName (String name) { this .name = name; } public int getAge () { return age; } public void setAge (int age) { this .age = age; } @Override public int compareTo (Object o) { if (this == o){ return 0 ; } if (o instanceof User){ User u = (User) o; int value = this .age - u.age; if (value !=0 ){ return value; } return -this .name.compareTo(u.name); } throw new RuntimeException ("类型不匹配" ); } @Override public String toString () { return "User{" + "name='" + name + '\'' + ", age=" + age + '}' ; } }
Properties的使用 Properties是Hashtable的子类,其key和value都是String类型的,常用来处理属性文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class PropertiesTest { @Test public void test () throws IOException { File file = new File ("info.properties" ); System.out.println(file.getAbsolutePath()); FileInputStream fis = new FileInputStream (file); Properties pros = new Properties (); pros.load(fis); String name = pros.getProperty("name" ); String pwd = pros.getProperty("password" ); System.out.println(name+"xx" +pwd); fis.close(); } }
Collections Collections是一个操作Set,List和Map等集合的工具类。
**Question:**Collection和Collections
Collection:集合框架中的用于存储一个一个元素的接口,又为List和Set等子接口
Collections:用于操作集合框架的一个工具类。此时集合框架包括:Set、List、Map
常用方法 排序操作:
reverse(list):反转list中的元素
shuffle(list):对list集合元素进行随机排序
sort(list):根据元素的自然顺序对指定List集合元素按升序排序
sort(list.Comparator):根据指定的Comparator产生的顺序对List集合元素进行排序
swap(list.int int):将指定list集合中i处元素和j处元素进行交换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Test public void test () { List list = Arrays.asList(45 ,34 ,64 ,23 ,23 ,12 ,11 ,24 ,5 ); System.out.println(list); Collections.shuffle(list); Collections.sort(list); Collections.sort(list, new Comparator (){ @Override public int compare (Object o1, Object o2) { if (o1 instanceof Integer && o2 instanceof Integer){ Integer i1 = (Integer) o1; Integer i2 = (Integer) o2; return -(i1- i2); } throw new RuntimeException ("类型不匹配" ); } }); System.out.println(list); }
查找:
Object max(Collection):根据元素自然排序,返回集合中最大的元素
Object max(Collection.Comparator):根据Comparator指定的顺序,返回给定集合中最大元素
Object min(Collection):根据元素的自然顺序,返回给定集合中最小的元素
Object min(Collection Comparator):根据Comparator指定的顺序,返回给定集合中最小元素
int binarySearch(List list, T key)在List集合中查找某个元素的小标。
int binarySearch(List list, T key,Comparator c)在List集合中查找某个元素的小标,
int frequency(Collection c, Object o):返回指定集合中指定元素出现的次数
复制:
void copy(List des List src):将src中的内容赋值到dest中
1 2 3 List src = Arrays.asList(45 ,34 ,64 ,23 ,23 ,12 ,11 ,24 ,5 );List dest = Arrays.asList(new Object [src.size()]);Collections.copy(dest,src);
boolean replaceAll(List list, Object oldVal, Object newVal):使用新值替换List对象中所有旧值
boolean addAll(Collection c, T..elements)将所有制定元素添加到指定collection中
Collections类中提供了多个synchronizedXXX()方法,该方法可使将指定集合包装成线程同步的集合
常见问题: List,Set,Map是否为Collection的接口,三者的区别? list,map,set接口的实现类,并说出其特点 集合的父类是谁?哪些安全的? 遍历集合的方式有哪些? 迭代器iterator用来遍历Collection,不能用来遍历Map
增强for
ArrayList与LinkedList区别? Set里的元素是不能重复的,那用什么来区分重复与否,用equals() hashCode()、equals()
TreeSet两种排序方式在使用的时候怎么起作用? 在添加新的的元素时,需要调用compareTo或compare()
TreeSet的数据结构 红黑树
final怎么用,修饰Map可以继续添加数据吗? Set和Map的比较 HashSet底层是HashMap
LinkedHashSet底层就是LinkedHashMap
TreeSet底层就是TreeMap
HashMap线程安全吗? 不安全。
Hashtable是怎么实现爱你的,为什么安全?
数组+单向链表;底层方法使用synchronized修饰
HashMap和TreeMap的区别 底层数据结果截然不同
HashMap里面实践装的是什么? JDK7:HashMap内部声明了Entry,实现了Map中Entry接口(key,value作为Entry两个属性出现)
JDK8:HashMap内部声明了Node,实现了Map中Entry接口(key,value作为Entry两个属性出现)
HashMap的key存储在哪里? 数组+链表+红黑树
自定义类型可以作为Key吗? 可以。要重写hashCode()和equals方法