JavaSE.08.集合
1.Collection
Collection采用线性列表的储存方式,单列数据
1.集合,数组都是对多个数据进行存储操作的结构,简称Java容器
说明:此时的存储,主要指的是内存层面的存储,不涉及到持久化的存储(.txt,.jpg...)
2.1数组在存储多个数据方面的特点
数组初始化以后长度就确定了
数组声明的类型,就决定了进行元素初始化的类型
2.2数组在存储多个数据方面的弊端
一旦初始化以后,其长度不可修改
数组中提供的方法非常有限,对于添加,删除,插入数据等操作,不方便
获取数组中实际元素的个数,数组没有现成的方法,属性可用
数组存储数据的特点:有序,可重复,对于无序或者不能重复的需求,无法做到
1.Collection中的方法
add(Object e)
addAll()
clear()清空集合元素
isEmpty()判断集合是否为空
contains(Object obj):判断集合中是否包含obj
containsAll(Collection col4):判断形参col4中的所有元素是否都存在于当前集合中
remove(Object obj):移出obj元素
removeAll(Collection col1):从当前集合中移出col1中的所有元素
col1.retainAll(Collection col2):取交集,并返回给当前集合
equals(Object obj):比较当前对象和形参对象中的元素是否全部相等
hashCode():返回当前对象的哈希值
toArray()集合转换为数组
Arrays.asList(objects)数组转换为集合
iterator():返回Iterator接口的实例,用于遍历集合元素
public class CollectionTest {
@Test
public void test1(){
Collection col1 = new ArrayList();
//add(Object e)
col1.add("aa");
col1.add(123);
col1.add(new Date());
col1.add(new String("Tom"));
col1.add(new Student("Jarry"));
//获取添加元素的个数
System.out.println(col1.size());
//addAll()
Collection col2 = new ArrayList();
col2.add("aa");
col2.add(123);
col2.add(new Date());
col1.addAll(col2);
System.out.println(col1.size());
System.out.println(col1);
//clear()清空集合元素
col1.clear();
//isEmpty()判断集合是否为空
System.out.println(col1.isEmpty());
//contains(Object obj):判断集合中是否包含obj
Collection col3 = new ArrayList();
col3.add(new String("Tom"));
col3.add(new Student("Jarry"));
col3.add(new Student("Jarry"));
boolean contains = col3.contains("aa");
System.out.println("--------------------------------");
System.out.println(col3.contains(new String("Tom")));
System.out.println(col3);
System.out.println(new Student("Jarry"));
System.out.println(col3.contains(new Student("Jarry")));//false --->重写equals方法true
//containsAll(Collection col4):判断形参col4中的所有元素是否都存在于当前集合中
System.out.println("------------------------------------");
Collection col4 = Arrays.asList(123,456);
System.out.println(col3.containsAll(col4));
System.out.println("------------------------------------");
//remove(Object obj):
Collection col5 = new ArrayList();
col5.add("aa");
col5.add(123);
col5.add(new Date());
col5.add(new String("Tom"));
col5.add(new Student("Jarry"));
col5.remove("aa");//true删除成功 false删除失败
col5.remove(new String("Tom"));
col5.remove(new Student("Jarry"));
System.out.println(col5);
System.out.println("------------------------------------");
//removeAll(Collection col1):从当前集合中移出col1中的所有元素
Collection coll1 = Arrays.asList(123,"aa");
col5.removeAll(coll1);
System.out.println(col5);
}
@Test
public void test2(){
Collection col1 = new ArrayList();
col1.add("aa");
col1.add(123);
col1.add(new Date());
col1.add(new String("Tom"));
col1.add(new Student("Jarry"));
Collection col2 = Arrays.asList(123,"bbb",new String("Tom"));
//col1.retainAll(Collection col2):取交集,并返回给当前集合
col1.retainAll(col2);
System.out.println(col1);
//equals(Object obj):比较当前对象和形参对象中的元素是否全部相等
Collection col3 = new ArrayList();
col3.add(123);
col3.add(new String("Tom"));
System.out.println(col3.equals(col1));
}
@Test
public void test3(){
Collection col1 = new ArrayList();
col1.add("aa");
col1.add(123);
col1.add(new Date());
col1.add(new String("Tom"));
col1.add(new Student("Jarry"));
//hashCode():返回当前对象的哈希值
System.out.println(col1.hashCode());
//toArray()集合转换为数组
Object[] objects = col1.toArray();
for (int i = 0; i < objects.length; i++) {
System.out.println(objects[i]);
}
//Arrays.asList(objects)数组转换为集合
System.out.println(Arrays.asList(objects));
System.out.println(Arrays.asList(new int[]{123,456}));//[[I@5e8c92f4]
System.out.println(Arrays.asList(123,456));//[123, 456]
System.out.println(Arrays.asList(new Integer[]{123,456}));//[123, 456]
//iterator():返回Iterator接口的实例,用于遍历集合元素
}
}
2.Iterator迭代器
使用Iterator接口
Iterator对象称为迭代器(设计模式的一种),用于遍历Collection集合中的元素
GOF给迭代器模式定义为:提供一种方法访问一个容器(Collection)对象中各个元素
而不需要暴露该对象的内部细节。迭代器模式,就是为容器而生。
public class MethodIteratorTest {
@Test
public void test1(){
Collection col1 = new ArrayList();
//add(Object e)
col1.add("aa");
col1.add(123);
col1.add(new Date());
col1.add(new String("Tom"));
col1.add(new Student("Jarry"));
//Iterator迭代器接口
//方式一
Iterator it = col1.iterator();
// System.out.println(it.next());
// System.out.println(it.next());
// System.out.println(it.next());
// System.out.println(it.next());
// System.out.println(it.next());
// System.out.println(it.next());//System.out.println(it.next());
//方式二
// for (int i = 0; i < col1.size(); i++) {
// System.out.println(it.next());
// }
//方式三
while (it.hasNext()){
System.out.println(it.next());
}
}
}
3.for-each
@Test
public void test3(){
String[] arr = new String[]{"MM","MM","MM"};
//普通for循环 "GG"
// for (int i = 0; i < arr.length; i++) {
// arr[i] = "GG";
// }
//for(元素类型 局部变量 :集合对象)
//内部调用迭代器
//foreach循环 "MM"
for (String str: arr ) {
str = "GG";
}
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
@Test
public void tset1(){
Collection list = new ArrayList();
list.add(12);
list.add(142);
list.add(512);
list.add(112);
list.add(122);
list.forEach(System.out::println);
}
2.Collection实现类
1.List
1.Collection接口:单列集合
List接口:储存有序的,可重复的数据-----“动态”数组,替换原有的数组
---ArrayList:线程不安全,效率高,底层用Object[] elementDate存储
---LinkedList:对于频繁的插入,删除,此类效率高,底层使用双向链表储存
---Vector:线程安全,效率低,底层用Object[] elementDate存储
2.ArrayList源码分析:
jdk7情况下:
ArrayList list = new ArrayList();空参构造器创建长度是10个Object[] elementDate数组
list.add()..//如果此次的添加导致底层elementDate数组容量不够,则扩容
默认情况下,扩容为原来的容量的1.5倍,同时要将原有的数据复制到新的数组中
结论:开发中使用带参数的构造器,ArrayList al = new ArrayList(50);
jdk8情况下:
ArrayList list = new ArrayList();此时的底层Object[] elementDate数组初始化为{}
并没有创建长度为10的数组
list.add()//第一次调用add()操作,底层才创建了长度10的数组,并添加数据,后续扩容不变
2.2小结:jdk7类似于单例的饿汉式,jdk8类似于单例的懒汉式,延迟了数组的创建时间,节省内存
3.LinkedList源码分析:
LinkedList list = new LinkedList();内部声明了Node类型的first和last属性,默认值为null
list.add()//将123封装到Node中,创建了Node对象
其中Node的定义,体现了LinkedList的双向链表结构
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
4.Vector源码分析:
jdk7和jdk8中通过Vector()构造器创建对象,底层都创建长度为10的数组
在扩容方面,扩容到原来的两倍
小结:Vector是线程安全,但是ArrayList可以通过Collections类的synchronizedList()方法变成线程安全的
5.ArrayList常用方法
增 add(E element)
删 remove(Object o)/remove(int index)
改 set(int index, E element)
查 get(int index)
插 add(int index, E element)
长度 size()
遍历 ①Iterator
②foreach
③普通循环
例题:ArrayList,LinkedList,Vector三者的异同?
同:都实现了List接口,存储数据的特点相同:有序,可重复
public class ListTest {
//List的常用方法
@Test
public void test1(){
ArrayList list = new ArrayList();
list.add(123);
list.add(333);
list.add("aa");
list.add(new Student("Tom"));
list.add(123);
//add(int index, E element)在index位置插入元素
list.add(1,"BB");
//addAll(Collection<? extends E> c)元素整体加入
//addAll(int index, Collection<? extends E> c)从index位置开始将元素加入
List<Integer> list1 = Arrays.asList(1, 2, 3);
list.addAll(list1);
System.out.println(list.size());
//get(int index)获取对应位置的元素
System.out.println(list.get(0));
//indexOf(Object o)返回元素首次出现的位置
System.out.println(list.indexOf(333));
//lastIndexOf(Object o)从后往前返回首次出现的位置
System.out.println(list.lastIndexOf(333));
//remove(Object o)按照对象元素删除
//remove(int index)按照脚标删除
list.remove("aa");
list.remove(3);
//set(int index, E element)修改指定位置的元素
list.set(1,"cc");
//subList(int fromIndex, int toIndex)找到一个左闭右开的子集合,不会影响集合本身
list.subList(1,5);
System.out.println("-------------------------");
//遍历1.
Iterator it = list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
System.out.println("-------------------------");
//2.
for (Object obj: list
) {
System.out.println(obj);
}
System.out.println("-------------------------");
//3.
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
}
2.Set
1.Collection接口:单列集合
Set接口:存储无序的,不可重复的
--HashSet:线程不安全,可以存储null值,底层数组
--LinkedHashSet:HashSet的子类,遍历其内部数据时,可以按照添加的顺序遍历
--TreeSet:底层“红黑树”,要求:添加同一类对象,按照指定属性进行排序,
2.Set:无序,不可重复
1.无序性:不等于随机性,存储的数据在底层数组中并非按照数组索引的顺序添加,根据数据的hashcode值决定
2.不可重复性:保证添加的元素按照equals()方法判断时,不能返回true,即,相同的元素只能添加一个
3.HashSet添加元素的过程
先调用hashcode()计算哈希值,通过算法计算确定在底层数组中存放位置
然后判断此位置元素:如果此位置没有元素,则添加成功
如果此位置有其他元素,则比较hash值
--如果hash值不相同,则添加成功
--如果值不相同,进而需要调用元素所在类的equals()方法:equals()确定添加的值和原有的值是否相同
--equals()返回true添加失败
--equals()返回false添加成功
--如果hashcode值相同但是元素的值不相同,则使用链表结构指向新的元素,这样减少相同值比较的个数
--jdk7:新元素指向原有的元素
--jdk8:原有的元素指向新元素
4.注意:Set中没有额外的新方法,使用的是Collection中的方法
5.要求:Set中添加的数据,其所在的类一定要重写hashcode()和equals()
重写的hashcode()和equals()尽可能保持一致性,相等的UI想必须具有相等的散列码(hashcode值)
public class SetTest {
@Test
public void test1(){
Set<Object> hs = new HashSet<>();//jdk数组长度16
hs.add(456);
hs.add("ccc");
hs.add(323);
hs.add(new Student("Tom"));
hs.add(new Student("Tom"));
hs.add("cds");
hs.add(false);
Iterator it = hs.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
}
@Test
public void test2(){
//LinkedHashSet作为HashSet的子类
//添加时也遵循无序性,但是通过双向链表结构记录添加前一个后一个数据,记录了添加顺序
//对于比较频繁的遍历操作,效率高于HashSet
HashSet<Object> hs = new LinkedHashSet<>();
hs.add(456);
hs.add("ccc");
hs.add(323);
hs.add(new Student("Tom"));
hs.add(new Student("Tom"));
hs.add("cds");
hs.add(false);
Iterator it = hs.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
}
@Test
public void test3(){
//向treeset中添加数据,要求是同一个类的数据
//特点:有序,查询快
//2.两种的排序方式:自然排序和定制排序
//自然排序中如果想要比较完名字比较年龄
//自然排序比较两个对象是否相同的标准是:compareTo()返回0,不在是equals
// @Override
// public int compareTo(Object o) {
// if(o instanceof Student){
// Student stu = (Student)o;
// int compare = this.name.compareTo(stu.name);
// if(compare != 0){
// return compare;
// }else{
// return Integer.compare(this.age,stu.age);
// }
// }else{
// throw new RuntimeException("输入的数据类型不匹配");
// }
// }
TreeSet<Object> hs = new TreeSet<>();
//ClassCastException
// hs.add(456);
// hs.add("ccc");
// hs.add(323);
// hs.add(new Student("Tom"));
// hs.add(new Student("Tom"));
// hs.add("cds");
// hs.add(false);
// hs.add(123);
// hs.add(22);
// hs.add(11);
// hs.add(21);
// hs.add(5);
//
// Iterator it = hs.iterator();
// while (it.hasNext()){
// System.out.println(it.next());
// }
hs.add(new Student("Tom"));
hs.add(new Student("jarry"));
hs.add(new Student("bom"));
hs.add(new Student("soul"));
hs.add(new Student("soul"));
//自然排序 实现comparable接口重写compareTo方法
Iterator it = hs.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
}
@Test
public void test4(){
Comparator co = new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof Student && o2 instanceof Student){
Student stu1 = (Student)o1;
Student stu2 = (Student)o2;
boolean boo = stu1.getName().equals(stu2.getName());
if (boo){
return 0;
}else {
return 1;
}
}else{
throw new RuntimeException("输入的数据类型不匹配");
}
}
};
TreeSet<Object> hs = new TreeSet<>();
hs.add(new Student("Tom"));
hs.add(new Student("jarry"));
hs.add(new Student("bom"));
hs.add(new Student("soul"));
hs.add(new Student("soul"));
Iterator it = hs.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
}
}
public class Student implements Comparable{
private String name;
public Student() {
}
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
//按照姓名从小到大排序
@Override
public int compareTo(Object o) {
if(o instanceof Student){
Student stu = (Student)o;
return this.name.compareTo(stu.name);
}else{
throw new RuntimeException("输入的数据类型不匹配");
}
}
}
//Set添加细节
public class SetTest {
@Test
public void test1(){
Set set = new HashSet();
Person p1 = new Person(1001,"AA");
Person p2 = new Person(1002,"BB");
set.add(p1);
set.add(p2);
System.out.println(set);
//[Person{id=1002, name='BB'}, Person{id=1001, name='AA'}]
p1.name = "CC";
System.out.println(set);
//[Person{id=1002, name='BB'}, Person{id=1001, name='CC'}]
set.add(new Person(1001,"CC"));
System.out.println(set);
//[Person{id=1002, name='BB'}, Person{id=1001, name='CC'}, Person{id=1001, name='CC'}]
set.add(new Person(1001,"AA"));
System.out.println(set);
//[Person{id=1002, name='BB'}, Person{id=1001, name='CC'}, Person{id=1001, name='CC'}, Person{id=1001, name='AA'}]
}
}
class Person{
int id;
String name;
public Person(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return id == person.id &&
Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
}
3.Map
1.HashMap
1.Map:双列数据,存储key-value对的数据
HashMap:(主要使用)线程不安全,效率高,可以存储null的key和value
LinkedHashMap:保证在遍历map元素时,可以按照添加顺序实现遍历
原因:在原有的HashMap底层结构基础上,添加了一对只恨,指向前一个和后一个的元素
对于频繁的遍历操作,此类执行效率高于HashMap
TreeMap:保证按照添加的key-value对进行排序,实现排序遍历,此时考虑key的自然排序或定制排序
底层使用的是红黑树,
Hashtable:(不常用)线程安全,效率低,不能储存null的key和value
Properties:常用来处理配置文件,key和value都是String类型
HashMap底层数据:数组+链表(jdk7及之前)
数组+红黑树(jdk8)
2.Map的结构理解key-value
Map中的key是无序的,不可重复的,使用Set存入所有的key----key所在的类要重写equals()和hashCode()以 HashMap为例
Map中的value:无序的,可重复的,使用Collection存储所有的value
一个键值对:key-value构成一个Entry对象,key-value是Entry的两个属性<k,v>
Map中的entry:无序的,不可重复的,使用Set存储所有的entry
3.HashMap的底层实现原理?以jdk7为例说明:
HashMap map = new HashMap();
在实例化以后,底层创建了长度是16的一维数组Entry[] table.
...多次添加
map.put(key1,value1);
首先,调用key1所在类的hashcode()计算key1哈希值,得到Entry数组中的存放位置,
如果此位置数据为null,key1和value1(entry)添加成功 ---情况1
如果此位置数据不为空,(意味着此位置存在一个或多个数据(以链表形式存在)),比较key1和已经存在的一个或多 个数据的哈希值,
如果哈希值与其他的都不相同,此时添加成功 ---情况2
如果哈希值和已经存在的某一个相同,继续调用key1的equals()进行比较,不相同则添加成功 ---情况3
,相同将使用value1替换相同key的value值(等同于修改value值)
补充:情况2和情况3:此时key1和value1和原来的数据以链表的方式储存
在不断添加的过程中,会设计扩容的问题,超出临界值(且存放的位置非空),
默认的扩容方式,扩容为原来容量的2倍,并将原有的数据复制过来
4.jdk8相比较于jdk7底层实现方面的不同
①.new HashMap():底层没有创建一个长度为16的数组
②.jdk8底层的数组是:Node[],而非Entry[]
③.首次调用put()方法时,底层创建长度为16的数组
④.jdk7底层结构只有:数组+链表,jdk8中底层结构:数组+链表+红黑树
当数组的某一个索引位置上的元素以链表形式存在的个数 > 8 且当前数组长度 > 64 时
此时此索引位置上的所有数据改为使用红黑树储存
DEFAULT_INITIAL_CAPACITY= 1 << 4:HashMap的默认容量,16
DEFAULT_LOAD_FACTOR = 0.75f:HashMap的默认加载因子
threshold:扩容的临界值,=容量*填充因子:16*0.75 => 12
TREEIFY_THRESHOLD = 8 :Bucket中链表长度大于该默认值,转化为红黑树
MIN_TREEIFY_CAPACITY = 64 :桶中的Node被树化时最小的hash表容量
5.总结方法
添加:put()
删除:remove()
修改:put()
查询:get()
长度:size()
遍历:keySet() / values() / entrySet()
例题:
①.HashMap的底层实现原理
②.HashMap和Hashtable的异同
③.CurrentHashMap和Hashtable的异同
public class MapTest {
@Test
public void test1(){
Map map = new HashMap();
map.put(123,"aa");
map.put(234,"ab");
map.put(345,"ac");
System.out.println(map);
Map map1 = new LinkedHashMap();//相比较于HashMap记录了添加的顺序
map1.put(123,"aa");
map1.put(234,"ab");
map1.put(345,"ac");
System.out.println(map1);
}
/**
* Description:常用方法
* author: Chen
* date: 2020/10/30 21:27
* return:
*/
@Test
public void test2(){
Map map = new HashMap();
//put()
//添加
map.put(123,"aa");
map.put(234,"ab");
map.put(345,"ac");
//修改
map.put(123,"bb");
System.out.println(map);
System.out.println("---------------");
Map map1 = new HashMap();
map1.put(2222,"ww");
map1.put(111,"cc");
//putAll()
map.putAll(map1);
System.out.println(map);
System.out.println("---------------");
//remove():按照key移除
Object val = map.remove(123);
System.out.println(val);
System.out.println(map);
System.out.println("---------------");
//clear():清空
map.clear();
System.out.println(map);
}
/**
* Description:元素查询操作
* author: Chen
* date: 2020/10/30 21:36
* return:
*/
@Test
public void test3(){
Map map = new HashMap();
map.put(123,"aa");
map.put(234,"ab");
map.put(345,"ac");
//get()
System.out.println(map.get(123));
//containsKey():判断key是否存在
System.out.println(map.containsKey(123));
//containsValue()
System.out.println(map.containsValue("aa"));
//isEmtry():是否为空
System.out.println(map.isEmpty());
//equals()
Map map1 = new HashMap();
map1.put(123,"aa");
map1.put(234,"ab");
map1.put(345,"ac");
System.out.println(map.equals(map1));
}
/**
* Description: 遍历Map
* author: Chen
* date: 2020/10/30 21:40
* return:
*/
@Test
public void test4(){
Map map = new HashMap();
map.put(123,"aa");
map.put(234,"ab");
map.put(345,"ac");
//keySet()
Set key = map.keySet();
Iterator iterator = key.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
System.out.println("----------------");
//遍历value
Collection value = map.values();
for (Object obj: value) {
System.out.println(obj);
}
System.out.println("----------------");
//entrySet():遍历key-value
Set set = map.entrySet();
Iterator iterator1 = set.iterator();
while (iterator1.hasNext()){
Object obj = iterator1.next();
Map.Entry entry = (Map.Entry)obj;
System.out.print(entry.getKey() + ":");
System.out.println(entry.getValue());
}
System.out.println("----------------");
//方式二
Set key1 = map.keySet();
Iterator iterator2 = key1.iterator();
while (iterator2.hasNext()){
Object keyObj = iterator2.next();
Object valueObj = map.get(keyObj);
System.out.println(keyObj + ":" + valueObj);
}
}
}
2.TreeMap
public class TreeMapTest {
/*
* 向TreeMap中添加key-value,要求key必须是由同一个类创建的对象
* 因为要按照key进行排序,自然排序,定制排序
*/
@Test
public void test1(){
TreeMap map = new TreeMap();
Student1 stu = new Student1("Tom",15);
Student1 stu1 = new Student1("Jarry",32);
Student1 stu2 = new Student1("Jack",14);
Student1 stu3 = new Student1("Rose",23);
map.put(stu,32);
map.put(stu1,23);
map.put(stu2,45);
map.put(stu3,55);
//自然排序
Set set = map.entrySet();
Iterator iterator1 = set.iterator();
while (iterator1.hasNext()){
Object obj = iterator1.next();
Map.Entry entry = (Map.Entry)obj;
System.out.print(entry.getKey() + ":");
System.out.println(entry.getValue());
}
}
@Test
public void test2(){
TreeMap map = new TreeMap(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof Student1 && o2 instanceof Student1){
Student1 s1 = (Student1)o1;
Student1 s2 = (Student1)o2;
return Integer.compare(s1.getAge(),s2.getAge());
}
throw new RuntimeException("输入的类型不匹配");
}
});
Student1 stu = new Student1("Tom",15);
Student1 stu1 = new Student1("Jarry",32);
Student1 stu2 = new Student1("Jack",14);
Student1 stu3 = new Student1("Rose",23);
map.put(stu,32);
map.put(stu1,23);
map.put(stu2,45);
map.put(stu3,55);
Set set = map.entrySet();
Iterator iterator1 = set.iterator();
while (iterator1.hasNext()){
Object obj = iterator1.next();
Map.Entry entry = (Map.Entry)obj;
System.out.print(entry.getKey() + ":");
System.out.println(entry.getValue());
}
}
}
public class Student1 implements Comparable{
private String name;
private int age;
public Student1() {
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student1(String name, int age) {
this.name = name;
this.age = age;
}
public Student1(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student1{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student1 student1 = (Student1) o;
return age == student1.age &&
Objects.equals(name, student1.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
//按照姓名从小到大排序
@Override
public int compareTo(Object o) {
if(o instanceof Student1){
Student1 stu = (Student1)o;
return this.name.compareTo(stu.name);
}else{
throw new RuntimeException("输入的数据类型不匹配");
}
}
}
3.CurrentHashMap
CurrentHashMap多线程高并发的数组应用,多个线程同时操作集合中分段的数据
是由Segment数组、HashEntry组成,和HashMap一样,仍然是数组加链表。
4.Collections
reverse(List):反转List中元素的顺序
shuffle(List):对list集合元素进行随机排列
sort():排序,实现comparable接口
sort(comparator):定制排序
swap()交换指定两个位置的元素
max(list):找最大值
max(list,Compareator):按照指定顺序返回最大元素
min(list):找最小值
min(list,Compareator):按照指定顺序返回最小元素
frequency(list,object)返回list中和643相同的第一个元素的脚标
Arrays.asList():将数组转换为集合
Collections.copy(dest,list)将list集合复制进入dest集合
Collections.synchronizedXxx()方法将集合转换为线程安全的并返回
public class CollectionsTest {
@Test
public void test(){
List list = new ArrayList();
list.add(123);
list.add(53);
list.add(643);
list.add(643);
list.add(643);
list.add(163);
list.add(12);
System.out.println(list);
//reverse(List):反转List中元素的顺序
Collections.reverse(list);
System.out.println(list);
//shuffle(List):对list集合元素进行随机排列
Collections.shuffle(list);
System.out.println(list);
//sort():排序,实现comparable接口
//sort(comparator):定制排序
//swap()交换指定两个位置的元素
Collections.swap(list,2,1);
System.out.println(list);
//max(list):找最大值
//max(list,Compareator):按照指定顺序返回最大元素
//min(list):找最小值
//min(list,Compareator):按照指定顺序返回最小元素
System.out.println(Collections.max(list));
//frequency(list,object)返回list中和643相同的第一个元素的脚标
System.out.println(Collections.frequency(list,643));
//List dest = new ArrayList();情况一:会产生异常
//Arrays.asList():将数组转换为集合
List dest = Arrays.asList(new Object[list.size()]);
//Collections.copy(dest,list)将list集合复制进入dest集合
Collections.copy(dest,list);//IndexOutOfBoundsException情况一
System.out.println(dest);
//Collections.synchronizedXxx()方法将集合转换为线程安全的并返回
List list1 = Collections.synchronizedList(list);
}
}
5.Properties
public class PropertiesTest {
public static void main(String[] args) throws IOException {
//Properties:常用来处理配置文件,key和value都是string类型
Properties pros = new Properties();
FileInputStream is = new FileInputStream("jdbc.properties");
pros.load(is);//加载流对应的文件
String name = pros.getProperty("name");
String passWord = pros.getProperty("password");
System.out.println(name + ":" + passWord);
}
}
public class CollectionTest {
public static void main(String[] args) {
//与配置文件对应的一个类
Properties p = new Properties();
// File file = new File("F:/idea-workspace/propertiestest/src/account.properties");
//默认的路径是项目的src路径下 而不是模块中的src
File file = new File("propertiestest/src/account.properties");
try {
InputStream is = new FileInputStream(file);
//将配置文件加载进来,参数需要一个输入流
p.load(is);
} catch (IOException e) {
e.printStackTrace();
}
//直接通过key值访问对应的内容
String pass1 = p.get("userbirth").toString();
String pass2 = p.get("userpass").toString();
System.out.println(pass1 + " " + pass2);
//使用当前类的类字节码加载器“反射”,读取文件为输入流
//文件的路径默认从src目录下寻找
Properties p1 = new Properties();
InputStream is1 = CollectionUtil.class.getClassLoader().getResourceAsStream("account.properties");
try {
p1.load(is1);
} catch (IOException e) {
e.printStackTrace();
}
String pass3 = p1.get("userbirth").toString();
System.out.println(pass3);
}
}
import java.io.*;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Set;
/**
* @author: chen
* @date: 2020/10/21 11:23
* @description:试着做一个collection工具类
* @function:
*/
public class CollectionUtil {
public static void main(String[] args) {
CollectionUtil.saveKey("boy","123456");
System.out.println(CollectionUtil.getValue("boy"));
System.out.println("============================================");
//枚举类获取到Properties里的key值 现在不常用被迭代器取代
Enumeration em = p.keys();
while (em.hasMoreElements()) {
Object obj = em.nextElement();
System.out.println(obj + "=" + p.getProperty(obj.toString()));
}
System.out.println("==============================");
Set set = p.keySet();
for (Object obj : set) {
System.out.println(obj + "=" + p.getProperty(obj.toString()));
}
}
private static final String FILEPATH = "propertiestest/src/account.properties";
private static Properties p;
/**
* Description:初始化配置文件,输入文件的路径读取并加载
* author: Chen
* date: 2020/10/21 11:44
* return:
*/
static {
p = new Properties();
InputStream is1 = CollectionUtil.class.getClassLoader().getResourceAsStream("account.properties");
try {
p.load(is1);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Description: 获取输入的键对应的值
* author: Chen
* date: 2020/10/21 11:44
* return:
*/
public static String getValue(String key){
return p.getProperty(key);
}
/**
* Description: 设置键和对应的值
* author: Chen
* date: 2020/10/21 11:43
* return:
*/
public static void saveKey(String key,String val){
//设置属性
OutputStream os = null;
try {
p.setProperty(key,val);
os = new FileOutputStream(new File(FILEPATH));
p.store(os,"new wirte");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(os != null)
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}