集合的框架概述
1.集合,数组都是对多个数据进行存储操作的结构,简称Java容器
说明:此时的存储,主要指内存层面的存储,不涉及持久性的存储
2.数组在存储多个数据方面的特点:
> 一旦初始化以后,长度就确定了
> 数组一旦定义好,其元素类型也就确定了
3.数组在存储多个数据方面的缺点
> 一旦初始化后长度不可修改
> 数组中提供的方法非常有限,且效率不高
> 数组存储数据的特点:有序,可重复。对于无须,不可重复的需求不能满足
Collection
Collection常用方法
public boolean add(E e): 把给定的对象添加到当前集合中 。
public void clear() :清空集合中所有的元素。
public boolean remove(E e): 把给定的对象在当前集合中删除。
public boolean contains(E e): 判断当前集合中是否包含给定的对象。
public boolean isEmpty(): 判断当前集合是否为空。
public int size(): 返回集合中元素的个数。
public Object[] toArray(): 把集合中的元素,存储到数组中。
注意:向Collection接口的实现类的对象中添加数据obj时,要求obj所在类重写equals方法。
Iterator迭代器
1.集合每次调用iterator方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素前。
2.内部定义了remove方法,可以在遍历的时候直接删除集合中的元素,区别于集合直接调用的remove()
public static void main(String[] args) {
Collection coll = new ArrayList();
coll.add(123);
coll.add(456);
coll.add(789);
Iterator iterator = coll.iterator();
while(iterator.hasNext())
{
Object ob = iterator.next();
if(ob.equals(123))
iterator.remove();
}
Iterator iterator1 = coll.iterator();
while(iterator1.hasNext())
{
System.out.println(iterator1.next());
}
for (Object o:coll
) {
System.out.println(o);
}
}
List
ArrayList,LinkedList源码分析
ArrayList分析:jdk7
ArrayList list = new ArrayList(); 底层创建长度为10 的Object[]数组elementDate
list.add(123); elementDate[0] = new Integer(123);
...
list.add(123); 如果此次添加导致底层的elementDate数组容量不够则扩容
默认情况下,扩容为原来的1.5倍;同时需要将原有数组中的数据复制到新的数组中
-----------------------------------------------------------------------------------------
jdk8中ArrayList中的变化:
ArrayList list = new ArrayList(); 底层数组初始化,并未创建长度
list.add(123) 第一次调用add才创建了长度为10 的数组
LinkedList的分析:
LinkedList list = new LinkedList(); 内部声明了Node类型的first和last属性并赋为null
list.add(123); 将123封装到Node中,创建了Node对象
ArrayList,LinkList,Vector三者异同
同:三者都是实现了List接口,存储数据的特点相同:有序,可重复
异:ArrayList:线程不安全,效率高,底层使用Object[] elementDate储存
LinkedList:底层使用双向链表储存
Vector:线程安全,效率低,底层使用Object[] elementDate储存
List常用方法
void add?(int index, E element) 将指定元素插入此列表中的指定位置
boolean addAll?(int index,Collection else) 从index位置开始将else中所有的元素插入
Object get(int index) 获取指定index位置的元素
int indexOf?(Object o) 返回此列表中第一次出现的指定元素的下标,如果此列表不包含该元素,则返回-1。
int lastIndexOf?(Object o) 返回此列表中指定元素最后一次出现的索引,如果此列表不包含该元素,则返回-1。
Object remove?(int index) 删除此列表中指定位置的元素。
Object set?(int index, E element) 使用指定的元素替换此列表中指定位置的元素
asList(T[] t) 数组转 List
toArray() List 转数组
Set
Set:储存无序的,不可重复的数据
以HashSet举例
1.无序性:无序性不等于随机性。储存的数据在底层数组中并非按照索引 的顺序添加,而是根据哈希值
2.不可重复性:保证添加的元素按照equals()判断时,不能返回true,即相同元素只能添加一个
注意:向Set接口的实现类的对象中添加数据obj时,要求obj所在类重写equals方法和HashCode方法。
HashSet
HashSet底层其实是用HashMap实现存储的
具体实现唯一性的比较过程:存储元素首先会使用hash()算法函数生成一个int类型hashCode散列值,然后已经的所存储的元素的hashCode值比较,如果hashCode不相等,则所存储的两个对象一定不相等,此时存储当前的新的hashCode值处的元素对象;如果hashCode相等,存储元素的对象还是不一定相等,此时会调用equals()方法判断两个对象的内容是否相等,如果内容相等,那么就是同一个对象,无需存储;如果比较的内容不相等,那么就是不同的对象,就该存储了,此时就要采用哈希的解决地址冲突算法,在当前hashCode值处类似一个新的链表, 在同一个hashCode值的后面存储存储不同的对象,这样就保证了元素的唯一性。
Set的实现类的集合对象中不能够有重复元素,HashSet也一样他是使用了一种标识来确定元素的不重复,HashSet用一种算法来保证HashSet中的元素是不重复的, HashSet采用哈希算法,底层用数组存储数据。默认初始化容量16,加载因子0.75。达到16*0.75后扩容(2倍)
Object类中的hashCode()的方法是所有子类都会继承这个方法,这个方法会用Hash算法算出一个Hash(哈希)码值返回,HashSet会用Hash码值去和数组长度取模, 模(这个模就是对象要存放在数组中的位置)相同时才会判断数组中的元素和要加入的对象的内容是否相同,如果不同才会添加进去。
LinkedHashSet
作为HashSet的子类,遍历其内部数据时,可以按照添加的顺序遍历
TreeSet
1.向TreeSet中添加的数据,要求是相同类的对象
2.俩种排序方式:自然排序(实现Comparable接口)和定制排序(Comparator)
3.对象是否相同的标准不再是equals而是俩种排序
Map
Map结构的理解:
1.Map中的key:无序的,不可重复的,使用Set存储所有的key
------>所在的类要重写equals,hashcode
2.Map中的values:无序的,可重复的,使用Collection存储所有的values
------>所在的类要重写equals
3.Map中的entry:无序的,不可出发点,使用Set存储所有的entry
HashMap
HashMap的底层原理:
jdk7
HashMap map = new HashMap();
在实例化后,底层创建了长度为16的一维数组Entry[] table
...经历多次put...
map.put(xxx,xxx);
首先,调用key所在类的hashcode计算key的哈希值,此哈希值经历算法计算后,得到Entry数组中存放的位置。
如果此位置为空,此时key-values添加成功 ---------情况1
如果此位置不为空,(意味着此位置存在一个或多个数据(以链表的形式存在)),比较key和已经存储的数据的哈希值:
如果key的哈希值与已经存在的数据的哈希值都不同,则此时key-values添加成功 --------情况2
如果key的哈希值和已经存在的某个数据的哈希值相同,继续比较(调用key所在的类的equals)
如果不相同,则此时key-values添加成功 --------情况3
如果相同,则将原来的values替换成新的values
补充:情况2,情况3的数据以链表形式存储
当数组达到:默认容量(16)*默认加载因子(0.75)= 扩容临界值(12)后数组扩容,扩容到原来的2倍
------------------------------------------------------------------------------------------------
jdk8
1.new 的时候仅声明,put的时候才创建长度为16的数组
2.底层为Node而非Entry
3.当数组某一个索引位置上的元素以链表形式存在的数据个数 > 8个 且当前数组长度 > 64时,
此时此索引上的所有数据改为用红黑树存储
遍历HashMap的四种方式
● keys() 获取所有 key,values() 获取所有 value
HashMap map = new HashMap();
map.put(1,1);
map.put(2,2);
map.put(3,3);
map.put(4,4);
map.put(5,5);
map.put(6,6);
Set<Integer> keys = map.keySet();
for (Integer key : keys) {
System.out.println(key);
}
Collection<Integer> values = map.values();
for (Integer value : values) {
System.out.println(value);
}
● 使用 Iterator 迭代器迭代
Iterator iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<Integer, Integer> mapEntry = (Map.Entry<Integer, Integer>) iterator.next();
System.out.println(mapEntry.getKey() + " === " + mapEntry.getValue());
}
● 使用 get 方式
Set<Integer> keySet = map.keySet();
for(Integer item: keySet) {
System.out.println( item + "====" + map.get(item));
}
● jdk1.8 后使用 Map 接口中的默认方法
map.forEach((key,value) -> {
System.out.println(key + "========" + value);
});
HashMap常用方法
Object put(Object key,Object values):插入/更新
void putAll(Map m):将m中的全部元素存放到现有的map中
Object remove(Object key):将指定key的key-values对删除
void clear():清空当前map所有数据
LinkedHashMap
TreeMap
Properties
public class MyProp {
public static void main(String[] args) throws IOException {
Properties prop = new Properties();
FileReader fileReader =
new FileReader(new File("Day12\\prop.properties"));
prop.load(fileReader);
fileReader.close();
System.out.println(prop);
System.out.println("===============");
Set<String> keys = prop.stringPropertyNames();
for (String key : keys) {
String value = prop.getProperty(key);
System.out.print(key+"\t"+value);
}
}
Collections
Collections与Collection的不同
Collections是工具类,不能被实例化。
而Collection是集合接口,包括List,Set。
Collections常用方法
public class CollectionsTest {
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list.add(34);
list.add(55);
list.add(56);
list.add(89);
list.add(12);
list.add(23);
list.add(126);
System.out.println(list);
Collections.sort(list);
System.out.println(list);
Collections.shuffle(list);
System.out.println(list);
int max = Collections.max(list);
int min = Collections.min(list);
System.out.println("Max:" + max + " Min: " + min);
List<String> list2 = Arrays.asList("Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday".split(","));
System.out.println(list2);
int index1 = Collections.binarySearch(list2, "Thursday");
int index2 = Collections.binarySearch(list2, "TTTTTT");
System.out.println(index1);
int n = -index2 - 1;
List<String> subList = Arrays.asList("Friday,Saturday".split(","));
int index3 = Collections.indexOfSubList(list2, subList);
System.out.println(index3);
int index4 = Collections.lastIndexOfSubList(list2, subList);
System.out.println(index4);
boolean flag = Collections.replaceAll(list2, "Sunday", "tttttt");
System.out.println(flag);
System.out.println(list2);
Collections.reverse(list2);
System.out.println(list2);
Collections.rotate(list2, 3);
System.out.println(list2);
List<String> list3 = Arrays.asList("copy1,copy2,copy3".split(","));
Collections.copy(list2, list3);
System.out.println(list2);
Collections.swap(list2, 0, 3);
System.out.println(list2);
Collections.fill(list2, "替换");
System.out.println(list2);
List<String> list4 = Collections.nCopies(5, "哈哈");
System.out.println(list4);
List<String> list5 = Arrays.asList("I love my country!".split(" "));
System.out.println(list5);
Enumeration<String> e = Collections.enumeration(list5);
while (e.hasMoreElements()) {
System.out.println(e.nextElement());
}
}
}
|