JAVA进阶
JAVA学习_集合
学习12.0
集合
概述
集合-容器
此时的存储主要是内存层面的存储
数组:
初始化后:长度不可变;元素类型确定;数组数据可重复;获取元素个数不变;方法有限;
Collection接口
单列集合
如果是自定义数据,需重写equals()方法
List:equals()
Set:(HashSet,LikedHashSet):equals(),hashCode();
(TreeSet):Comparable:CompareTo(Object obj);
Comparator:Compare(Object o1,Object o2);
接口中方法的使用(14种:5+9,如下)
Collection c1=new ArrayList();
Collection c2=new ArrayList();
1 c1.add();
2 c1.size();
3 c1.adAll(c2); c2添加到c1中
4 c1.isEmpty();
5 c1.clear(); 清空
Collection c1=new ArrayList();
c1.add(123);
c1.add("abc");
c1.add(false);
c1.add(new Person("lili",18));
// 1 contains() 判断当前集合是否包含obj
boolean contains=c1.contains(123);
System.out.println(contains);
System.out.println(c1.contains(new String("lili")));
boolean contains1=c1.contains(new Person("lili",18));
System.out.println(contains1);//false //自定义类一般要重写equals()
System.out.println(c1);
// 2 containsAll()
Collection c2=new ArrayList();
c2.add(123);
c2.add("abc");
c2.add(false);
c2.add(new Person("lili",18));
System.out.println(c1.containsAll(c2));
System.out.println("-------------------------");
// 3 remove(Object obj)从当前集合中移除obj
c1.remove(123);
System.out.println(c1);
// 4 removeAll(Collection c) 差集: 移除集合c(一样的)
Collection c3=Arrays.asList(123,"abc",4567);
c1.removeAll(c3);
System.out.println(c1);
// 5 retainAll(Collection c) 交集:保留一样的,删除不一样的
c2.retainAll(c3);
System.out.println(c2);
// 6 equals(Obeject obj) 完全相同且顺序一样才为真
System.out.println(c1.equals(c3));
// 7 hashCode() 返回当前对象的哈希值
System.out.println(c1.hashCode());
// 8 集合--->数组:toArray()
Object[] arr=c1.toArray();
for(int i=0;i<arr.length;i++)
{
System.out.println(arr[i]);
}
// 8.1 数组--->集合 : asList()
List<String> list= Arrays.asList(new String[]{"aa","ss","dd","ff"});
System.out.println(list);
List l1=Arrays.asList(new int[] {123,456});
System.out.println(l1.size());//1
List l2=Arrays.asList(new Integer[] {123,456});
System.out.println(l2.size());//2
List l3=Arrays.asList(123,45);
System.out.println(l3.size());//2
// 9 iterator() 迭代器, 返回Iterator接口的实例,用于遍历集合元素,放在IteratorTest.java中测试
Iterator iterator=c1.iterator();
//方式三:推荐
while(iterator.hasNext()) //hasNext 判断是否还有下一个元素
{
System.out.println(iterator.next()); //next指针下移
}
// Iterator中的remove:在遍历的时候删除
Iterator iterator=c1.iterator();
System.out.println(c1);
while(iterator1.hasNext())
{
Object obj=iterator1.next();
if("abc".equals(obj))
{
iterator1.remove();
}
}
while(iterator1.hasNext())
{
System.out.println(iterator1.next());
}
使用foreach循环,遍历集合,数组
//for(集合元素的类型 局部变量:集合对象)
//内部还是迭代器
for(Object obj:c4)
{
System.out.println(obj);
}
练习
String[] arr1=new String[] {"aa","ss","dd"};
// //方式一:普通for循环,原数组变了
// for(int i=0;i<arr1.length;i++)
// {
// arr1[i]="lkjhg";
// }
//方式一:增强for循环 ,原数组不变
for(String s:arr1)
{
s="lkjhg";
}
List
存有序的,可重复的,“动态”数组
ArrayList,LinkedList,Vector三者异同?
同:都实现了list接口,存有序的,可重复的,
ArrayList:作为list的主要实现类;线程不安全,效率高;底层使用Object[] elementData存储
LinkedList:对于频繁的插入、删除操作,使用此类效率比ArrayList高; 底层使用双向链表存储;
Vector:作为list的古老实现类; 线程安全,效率低;底层使用Object[]存储
List接口常用方法
常用 的:
增:add
删:remove
改:set
查:get
插;add
长度:size
遍历:Iterator迭代器;增强for循环;普通for循环;
例:
// 1 void add(int index,Object ele);在index位置插入ele
list.add(2, 000);
System.out.println(list);
// 2 boolean addAll()
List list1=Arrays.asList(1,2,3);
list.addAll(list1);
System.out.println(list);
// 3 Object get(int index); 按照索引获取
System.out.println(list.get(1));
// 4 int indexOf(Object obj);返回obj在集合中首次出现的位置,如果不存在返回-1
System.out.println(list.indexOf(456));
// 5 int lastIndexOf(Object obj);返回obj在集合中最后一次出现的位置
System.out.println(list.lastIndexOf(789));
// 6 Object remove(int index);移除指定位置的元素,并返回此元素
Object obj=list.remove(2); //删的是位置2的
// list.remove(new Integer(2); //删的是数据2
System.out.println(obj);
System.out.println(list);
// 7 Object set(int index,Object ele); 设置指定位置元素为ele
list.set(0, "aaa");
System.out.println(list);
// 8 List subList(int fromindex,int toindex);返回[fromindex,toindex),左闭右开
List list2=list.subList(2,4);
System.out.println(list2);
// 9 遍历
//方式一:迭代器
Iterator iterator=list.iterator();
while(iterator.hasNext()) //hasNext 判断是否还有下一个元素
{
System.out.println(iterator.next()); //next指针下移
}
//方式二:增强for循环
for(Object obj1:list)
{
System.out.println(obj1);
}
//方式三:普通for循环
for(int i=0;i<list.size();i++)
{
System.out.println(list.get(i));
}
ArrayList
源码分析:jdk7
造对象时创建数组
若数组容量不够,默认情况下扩为原来的1.5倍
建议开发中使用带参的构造器 ArrayList list=new ArrayList(int capacity);
源码分析:jdk8中的变化
第一次调用add时才创建数组(节省内存)
LinkedList
源码分析
底层用链表存储
LinkedList l=new LinkedList(); 内部声明了Node类型的first和last属性,默认值为null
l.add(123); 将123封装到Node中,创建了Node对象
其中,Node定义了 next,prev ; 体现了双向链表
Vector
源码分析:
通过Vector()创造构造器时,都创建了长度为10的数组
扩容时都扩大2倍
Set
存无序的(不是随机的):不可重复的,
Set接口没有定义新的方法
HashSet,LinkedHashSet,TreeSet ?
HashSet:作为Set接口的主要实现类;线程不安全;可以存null值
------LinkedHashSet:是HashSet的子类;遍历其内部数据时,可以按照添加的顺序遍历;效率更高
TreeSet:可以按照添加的对象指定属性进行排序
添加元素的过程:以HashSet为例:
哈希值不一样时,元素肯定不一样;
哈希值一样,equal不一样时,元素不一样;
为什么写hashCode()方法,有31这个数字?
选择尽量大的系数,减少冲突;
要求:
像Set添加时一定要重写hashCode()和 equals();且尽可能保持一致性
一般直接生成;
HashSet
无序性(不是随机的):存的数据并不是按照数组索引的顺序添加,和哈希值有关
不可重复性:保证添加的元素按照equals()判断时,不能返回true,即相同的元素只能添加一个;
底层原理和HashMap一样
LinkedHashSet
在添加数据的同时,每个数据还维护了两个引用,记录此 数据的前一个数据和后一个数据
TreeSet
添加的数据要求是相同类的对象;
按照从小到大排
两种排序方式:
自然排序:比较两个对象是否相同的标准:compareTo()返回0
定制排序:比较两个对象是否相同的标准:compareTo()返回0
Map接口
双列集合,用来存储一对(key,value)的数据,可以多对一;
实现类:HashMap,LinkedHashMap,TreeMap,Hashtable ?
HashMap:作为map的主要实现类;线程不安全,效率高;存储null的key和value;
------LinkedHashMap:hashMap的子类;保证遍历时可以按照添加的顺序遍历(底层加了指针);效率更高
TreeMap:保证按照太黏的key-value对进行排序;底层使用红黑树;
Hashtable:作为古老实现类;线程安全,效率低;不能存储null的key和value;
------Properties:Hashtable的子类;常用来处理配置文件。key,value都是String 类型
Map中的key:无序的,不可重复的;使用set存储
Map中的value:无序的,可重复的;使用collection存储
一个键值对:key-value构成了一个Entry对象
map常用方法
添加:put
删除:remove
修改:put
查询:get
长度:size
遍历:
如下
Map map=new HashMap();
// 1 添加 put
map.put("aa", 123);
map.put("bb", 123);
map.put("cc", 789);
map.put("dd", 123);
map.put(111, 321);
System.out.println(map);
// 2 修改
map.put("aa", 456);
// 3 移除 remove(key)
Object value=map.remove("dd");
System.out.println(value);
System.out.println(map);
// 4 查 get,containsKey,containsValue
System.out.println(map.get("aa"));
boolean isExist=map.containsKey("bb");
System.out.println(isExist);
boolean isExist1=map.containsValue(123);
System.out.println(isExist1);
// 5 清空
// map.clear(); // 不等于 map=null
// System.out.println(map.size());
// 6 是否为空
System.out.println(map.isEmpty());
// 7 遍历
//遍历所有的key集:keySet()
Set set=map.keySet();
Iterator iterator=set.iterator();
while(iterator.hasNext())
{
System.out.println(iterator.next());
}
System.out.println();
//遍历所有的value:
Collection valus=map.values();
for(Object obj:valus)
{
System.out.println(obj);
}
//遍历所有的key-value
//方式一:entrySet()
Set entryset=map.entrySet();
Iterator iterator1=entryset.iterator();
while(iterator1.hasNext())
{
Object obj=iterator1.next();
Map.Entry entry=(Map.Entry) obj;
System.out.println(entry.getKey()+"--->"+entry.getValue());
}
//方式二:
Set set1=map.keySet();
Iterator iterator2=set.iterator();
while(iterator2.hasNext())
{
Object key=iterator2.next();
Object keyvalue=map.get(key);
System.out.println(key+"------"+keyvalue);
}
HashMap
底层:
数组+链表(jdk7之前)
数组+链表+红黑树(jdk8)
底层实现原理(jdk7)
底层实现原理(jdk8)
加载因子决定数据密度;
LinkedHashMap
TreeMap
Hashtable
Properties
//处理配置文件
Properties pros =new Properties();
FileInputStream fis=new FileInputStream("jdbc.properties");
pros.load(fis);
String name=pros.getProperty("name");
String password=pros.getProperty("password");
System.out.println("name="+name+",password="+password);
Collections工具类
操作Collection,map的工具类
Collection 和Collections 的区别?
Collection:实现List和Set的接口
Collections:操作map和list的工具类
List list =new ArrayList();
list.add(123);
list.add(98);
list.add(0);
list.add(-55);
list.add(98);
//reverse(list); 反转
//shuffle(list); 随机排序
//sort(list); 自然排序,升序
//swap(list,int i,int j);list的i和j交换
Collections.reverse(list);
Collections.shuffle(list);
Collections.sort(list);
Collections.swap(list, 1, 3);
System.out.println(list);
//int frequency(Collection,Object);返回指定元素的出现次数;
int fre=Collections.frequency(list, 98);
System.out.println(fre);
//void copy(List dest,List src);将src复制到dest中
List dest =Arrays.asList(new Object[list.size()]);
Collections.copy(dest, list);
System.out.println(dest);
System.out.println(list);
/*
* Collections 类提供了多个synchronizedXxx()方法
* 该方法可将指定集合包装成线程同步的集合,从而可以解决
* 多线程并发访问集合时的线程安全问题
*
* 返回的list1线程安全
*/
List list1=Collections.synchronizedList(list);
ArrayList和HashMap都是线程不安全的,但是可以转成线程安全的,举例如上