collection接口中的实现类的对象添加的数据都是object类型,都是对象 ,因此对象都有其所在类,不可以添加基本数据类型,添加的基本数据类型也都是装箱之后的包装类
单列集合,用来存储一个一个的对象
Collection接口中有List接口和Set接口。
List接口:存储有序的、可重复的数据
Set接口:存储无序的、不可重复的数据
因此set和list接口的实现类可以使用collection接口中的方法,collection接口(父接口)的方法,在子接口以及实现类中都可以使用
add用法: collection接口中的实现类的对象添加的数据都是object类型,都是对象 ,因此对象都有其所在类,不可以添加基本数据类型,添加的基本数据类型也都是装箱之后的包装类。
contains用法: 要求collect接口实现类的对象中添加数据obj时候,要求obj所在类要重写equals方法。
Collection coll = new ArrayList();
//1.add
coll.add(new String("TOM");
//2.contains
coll.contains(new String("TOM"))//true,因为String类中重写了equals方法
coll.add(new Person("jerry",10));
coll.contains(new Person("jerry",10));
//如果没有重写equals方法,调用的就是父类Object的equals,Object中的equals就是==,也就是会比较地址值,因此输出false
//因此,需要定义的Person类重写equals方法,输出true
Collection coll1 = Arrays.asList(123,4567);
//3.containsAll
sout(coll.containsAll(coll1));//判断coll1中的所有元素是否都在coll中
//4.remove(Object obj)
Collection coll = new ArrayList();
coll.add(123);
coll.add(456);
//remove调用equals方法
coll.remove(1234);
coll.remove(123);
//5.retrainAll(Collection coll1):交集,获取当前集合和coll1集合的交集,并返回给当前集合,没有返回值,直接修改原数组
//6.equals(Object obj):要想返回true,当前集合和形参集合的元素都相同,区分array集合和hash集合,注意顺序
//7.hashcode
//8.集合——数组
Object[] arr = coll.toArray();
//9.数组——集合
List<String> list = Arrays.asList(new String[]{"AA","BB","CC"});
//注意
List arr1 = Arrays.asList(new int[]{1,2})//识别为1个元素,打印出来是地址
List arr1 = Arrays.asList(new Integer[]{1,2})//识别为2个元素
//iterator():返回Iterator接口的实例,用于遍历集合元素
1.内部的方法:hasNext()和next()方法
2.集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前
3.内部定义了remove(),可以在遍历的时候,删除集合中的元素。此方法不同于collection中的remove
while(iterator.hasNext()){
sout(iterator.next());
}
Iterator iterator = coll.iterator();
while((iterator.next())!=null){
sout(iterator.next());
}
while(coll.iterator().hasNext()){
sout(coll.iterator().next());
}
用于遍历集合和数组
//for(集合元素类型 局部变量 :集合对象)
//内部仍然调用了迭代器
for(Object obj:coll){
sout(obj);
}
String []arr = new String[]{"mm","mm","mm"};
//方式一:普通for赋值,输出是gg
fot(int i=0;i<arr.length;i++){
arr[i] = "gg";
}
//方式二:for each增强for循环,输出是gg
for(String s:arr){
s="gg";
}
//相当于把arr重新赋值给s,因此arr的值不变,s的值为gg
for(int i =0;i<arr.length;i++){
sout(arr[i]);
}
集合和数组存储数据: 集合和数组都是对多个数据进行存储操作的结构,简称Java容器
不同之处
1.数组:
String[] arr;
int [] arr1;
Object [] arr2;
2.集合的优点
存储有序的、可重复的数据
动态数据,替换原有的数组
常用的实现类有:ArrayList,LinkedList,Vector
三者的异同?
ArrayList list = new ArrayList();//底层创建了长度是10的Object[]数组elementData
list.add(123);//elementData[0]=new Integer(123);
……
list.add(11);//当添加的元素个数,如果此次的添加导致底层elementData数组容量不够,则扩容。默认扩容为原来数组长度的1.5倍,同时将原有数组中的数据复制到新的数组中
结论:开发中使用带参的构造器ArrayList list = new ArrayList(int capacity)
ArrayList list = new ArrayList();//底层Object[]elementData初始化为{},并没有创建长度为10的数组
list.add(123);//第一次调用add()时,底层才创建了长度为10的数组,并将数据123添加到elementData[0]
小结:jdk7中ArrayList对象的创建类似于单例的饿汉式,jdk8中ArrayList对象的创建类似于单例的懒汉式,延时了数组的创建,节省内存
LinkedList list = new LinkedList();//内部声明了Node类型的first和last属性,默认值为null
list.add(123);//将123封装到Node中,创建了Node对象
其中,Node定位体现了LinkedList的双向链表的说法
add
LinkedList<String> linkedList = new LinkedList<>();
linkedList.add("first");
linkedList.add("second");
linkedList.add("third");
System.out.println(linkedList);//[first,second,third]
linkedList.addFirst("addFirst");
System.out.println(linkedList);//[addFirst,first,second,third]
linkedList.addLast("addLast");
System.out.println(linkedList);//[addFirst,first,second,third,addLast]
linkedList.add(2, "addByIndex");
System.out.println(linkedList);//[addFirst,first,addByIndex,second,third,addLast]
remove
LinkedList<String> linkedList = new LinkedList<>();
linkedList.add("first");
linkedList.add("second");
linkedList.add("second");
linkedList.add("third");
linkedList.add("four");
linkedList.add("five");
System.out.println(linkedList);//[first,second,second,third,four,five]
linkedList.remove();
System.out.println("remove: " + linkedList);//remove: [second,second,third,four,five]
linkedList.remove("second");
System.out.println("remove(Object): " + linkedList);//remove(Object):[second,third,four,five]
linkedList.remove("six");
System.out.println("remove(Object) not exist: " + linkedList);//remove(Object) not exist: [second,third,four,five]
linkedList.remove(2);
System.out.println("remove(index): " + linkedList);//[second,third,five]
linkedList.removeFirst();
System.out.println("removeFirst: " + linkedList);//[third,five]
linkedList.removeLast();
System.out.println("removeLast:" + linkedList);//[third]
linkedList.clear();//
linkedList.add("first");
linkedList.add("second");
linkedList.add("first");
linkedList.add("third");
linkedList.add("first");
linkedList.add("five");
System.out.println(linkedList);//[first,second,first,third,first,five]
linkedList.removeFirstOccurrence("first");
System.out.println("removeFirstOccurrence: " + linkedList);//[second,first,third,first,five]
linkedList.removeLastOccurrence("first");
System.out.println("removeLastOccurrence: " + linkedList);//[second,first,third,five]
get
链表前后没有发生变化,只是取出来数
push、pop、poll
LinkedList<String> linkedList = new LinkedList<>();
linkedList.push("first");
linkedList.push("second");
linkedList.push("second");
linkedList.push("third");
linkedList.push("four");
linkedList.push("five");
System.out.println("linkedList: " + linkedList);//[five,four,third,second,second,first]
System.out.println("pop: " + linkedList.pop());//pop: first
System.out.println("after pop: " + linkedList);//after pop:[four,third,second,second,first]
System.out.println("poll: " + linkedList.poll());//poll:four
System.out.println("after poll: " + linkedList);//after poll:[third,second,second,first]
push和pop的操作接近stack的操作
poll和pop的区别
LinkedList<String> linkedList = new LinkedList<>();
System.out.println("poll: " + linkedList.poll());//poll:null
System.out.println("pop: " + linkedList.pop());//Exception in thread "main" java.util.NoSuchElementException
peek
LinkedList<String> linkedList = new LinkedList<>();
linkedList.push("first");
linkedList.push("second");
linkedList.push("second");
linkedList.push("third");
linkedList.push("four");
linkedList.push("five");
System.out.println("linkedList: " + linkedList);//linkedList:[five,four,third,second,second,first]
System.out.println("peek: " + linkedList.peek());//peek:five
System.out.println("peekFirst: " + linkedList.peekFirst());//peekFirst:five
System.out.println("peekLast: " + linkedList.peekLast());//peekLast:first
System.out.println("linkedList: " + linkedList);//linkedList:[five,four,third,second,second,first]
offer
LinkedList<String> linkedList = new LinkedList<>();
linkedList.push("first");
linkedList.push("second");
linkedList.push("second");
linkedList.push("third");
linkedList.push("four");
linkedList.push("five");
System.out.println("linkedList: " + linkedList);//linkedList:[five,four,third,second,second,first]
linkedList.offer("six");
System.out.println("linkedList: " + linkedList);//linkedList:[five,four,third,second,second,first,six]
linkedList.offerFirst("zero");
System.out.println("linkedList: " + linkedList);//linkedList:[zero,five,four,third,second,second,first,six]
linkedList.offerLast("seven");
System.out.println("linkedList: " + linkedList);//linkedList:[zero,five,four,third,second,second,first,six,seven]
其他常用方法中,只有set会改变原链表
System.out.println("linkedList: " + linkedList);
//linkedList:[five, four, third, second, second, first]
System.out.println("linkedList.contains(\"second\"): " + linkedList.contains("second"));//linkedList.contains("second"):true
System.out.println("linkedList.contains(\"six\"): " + linkedList.contains("six"));//false
System.out.println("linkedList.element(): " + linkedList.element());//5个元素
System.out.println("linkedList: " + linkedList);
System.out.println("linkedList.set(3, \"set\"): " + linkedList.set(3, "set"));
System.out.println("linkedList: " + linkedList);//linkedList: [five, four, third, set, second, first]
System.out.println("linkedList.subList(2,4): " + linkedList.subList(2,4));//linkedList.subList(2,4): [third, set]
System.out.println("linkedList: " + linkedList);
一、存储无序、不可重复的数据
具体实现类:
set接口中没有额外定义新的方法,使用的都是collection中的方法
要求:向set中添加的数据,其所在的类一定要重写hashcode()和equals()
重写的hashcode()和equals()尽可能保持一致性,相等的对象必须具有相等的散列码
二、添加元素的过程
首先调用元素所在类的hashCode方法,计算元素a的hash值,此哈希值接着通过某种算法计算出在HashSet底层数组中的存放位置(即为索引位置),判断数组此位置上是否已经有元素存在
三、TreeSet
1.向TreeSet中添加的数据,要求是相同类的对象
2.两种排序方式:自然排序(实现compareTo接口)和定制排序
3.自然排序中,比较两个对象是否相同的标准为:compareTo返回0,不再是equals
存储双列数据,存储key-value对的数据
实现类:
HashMap: 作为Map的主要实现类;线程不安全,效率高;可以存储null的key和value
TreeMap: 有序存储。保证按照添加的key-value对进行排序,实现排序遍历。此时考虑key的自然排序或定义排序。底层使用红黑树
Hashtable: 作为Map的古老实现类;线程安全,效率低;有sychronized,不能存储null的key和value
key:不重复,无序的。用set存储
value:可重复,无序。用collection存储
entry键值对:其中有两个对象k和v,无序,不可重复。用set存储
JDK7:
HashMap map = new HashMap();
实例化之后,底层创建了长度是16的一维数组Entry[] table。
map.put(key1,value1);
首先,调用key1所在类的hashcode()计算key1的哈希值,此哈希值经过某种算法计算之后,得到entry数组中的存放位置。
如果此位置上的数据为空,此时的entry添加成功
如果此位置上的数据不为空,(意味着此位置上存在一个或多个数据(以链表形式存在)),比较key1和已经存在的一个或多个数据的哈希值:
补充:如果数据不为空时,则新添加的数据和原来的数据以链表的方式存储
扩容方式:扩容为原来的两倍,并把原有数据复制过来
jdk8和jdk7的不同:
1.new HashMap():底层没有创建一个长度为16的数组
2.底层的数组是Node(),而非Entry()
3.首次调用put()方法时候,底层创建长度为16的数组
4.jdk7底层为数组+链表,jdk8底层为数组+链表+红黑树
当数组的某一个索引位置上的元素以链表形式存在的数据个数>8且当前数组的长度>64时,此时此索引位置上的所有数据改为使用红黑树存储。
map放数据使用put 函数,是尾插法。
//添加删除和修改
Map map = new Map();
//添加
map.put("AA",123);
map.put(45,123);
map.put("bb",56);
//修改
map.put("AA",87)
sout(map);
Map map1 = new Map();
map1.put("CC",123);
map1.put("DD",123);
map.putAll(map1);
//remove(key)修改
Object value = map.remove("CC");//移除指定key的键值对,并返回value,如果key值不存在,则返回null
//clear()
map.clear();//只是清空数据,map仍然存在
sout(map.size())//不会报空指针
sout(map)//{}
//元素查询的方法
map.get("CC");//获取指定key对应的value
//是否包含指定的key
boolean isExist = map.containsKey("BB");//是否包含指定的key
boolean isExist2 = map.constainsValue(123);//是否包含指定的value
//int size()返回map中key-value的个数
//boolean isEmpty()判断当前map是否为空
遍历
元视图操作的方法:
Set keySet():返回所有key构成的Set集合
Collection values():返回所有value构成的Collection
Set entrySet():返回所有key-value对构成的Set集合
Map map = new Map();
map.put("AA",123);
map.put(45,123);
map.put("bb",56);
//遍历所有的key集:keySet()
Set set = map.keySet();
Iterator iterator = set.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
//遍历所有的value集:values
Collection values = map.values();
for(Object obj:values){
sout(obj)
}
//遍历所有的key-value
Set entrySet = map.entrySet();
Iterator iterator1 = entrySet.iterator();
while(iterator1.hasNext()){
}