集合
1.集合框架
用于存储数量不等的多个对象,还可用于保存具有映射关系的关联数组
-
Java集合可分为
Collection
和Map
两种体系
Collection接口
Set
:元素无序,不可重复的集合----(类似数学中的集合)
List
:元素有序,可重复的集合----("动态"数组)
Map接口:具有映射关系----(类似数学中的函数) -
数组存储对象的缺点:创建后,长度不可变;数组存放的对象的个数不可知
2.Collection接口API
常见的接口API
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import org.junit.Test;
public class Test8{
@Test
public void testCollection(){
Collection coll = new ArrayList();
//1.size():返回集合中元素的个数
System.out.println(coll.size());//0
//2.add(Object obj):向集合中添加一个元素
coll.add(123);
coll.add("ABC");
coll.add(new Object());
coll.add(true);
System.out.println(coll.size());//4
//3.addAll(Collection coll):将形参coll中包含的所有元素添加到当前集合中
Collection coll1 = Arrays.asList(1,2,3);//添加3个元素到coll1中,coll1长度不可变,且不支持add()、remove()、clear()等方法
coll.addAll(coll1);
System.out.println(coll.size());//7
//查看集合元素
System.out.println(coll);
//4.判断集合是否为空
System.out.println(coll.isEmpty());//false
//5.clear():清空集合元素
coll.clear();
System.out.println(coll.isEmpty());//true
}
@Test
public void testCollection1(){
Collection coll = new ArrayList();
coll.add(123);
coll.add("ABC");
coll.add(new Object());
coll.add(true);
//6.contains(Object obj):判断集合中是否包含指定的obj元素,包含,返回true,不包含,返回false
//判断的依据:根据元素所在类的equals()方法来判断
//注意:如果存入集合中的元素是自定义类的对象,要求:自定义类要重写equals()方法
boolean b1 = coll.contains("ABC");
System.out.println(b1);//true
//7.containsAll(Collection coll):判断当前集合中是否包含coll中所有的元素
Collection coll1 = new ArrayList();
coll1.add(123);
coll1.add("ABC");
boolean b2 = coll.containsAll(coll1);
System.out.println(b2);//true
//8.retainAll(Collection coll):求当前集合与coll共有的元素,并返回给当前集合
coll.retainAll(coll1);
System.out.println(coll);//[123, ABC]
//9.remove():删除集合中的obj元素,删除成功,返回true,反之,返回false
boolean b3 = coll.remove(123);
System.out.println(b3);
//10.removeAll(Collection coll):从当前集合中删除包含在coll中的元素
Collection coll2 = new ArrayList();
coll2.add("ABC");
coll2.add("ACE");
coll.removeAll(coll2);
System.out.println(coll);//空(上一步后coll只剩ABC元素)
}
@Test
public void testCollection2(){
Collection coll = new ArrayList();
coll.add(123);
coll.add("ABC");
coll.add(new Object());
coll.add(true);
Collection coll1 = new ArrayList();
coll.add(123);
coll.add("ABC");
//11.equals(Collection coll):判断集合中的元素是否完全一样
//System.out.println(coll.equals(coll1));//false
//12.hashCode():算出集合哈希值
//System.out.println(coll.hashCode());
//13.toArray():将集合转化成数组
Object[] obj = coll.toArray();
for(int i = 0;i < obj.length;i++){
System.out.println(obj[i]);
}
//14.iterator():返回一个Iterator接口的实现类,进而实现集合的遍历
Iterator iterator = coll.iterator();
System.out.println("开始打印集合元素");
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
3.lterator迭代器接口
集合的遍历
方法一:使用lterator迭代器接口实现集合的遍历
正确写法:
public void testCollection2(){
Collection coll = new ArrayList();
coll.add(123);
coll.add("ABC");
coll.add(new Object());
coll.add(true);
Iterator iterator = coll.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
错误写法:
public void testCollection2(){
Collection coll = new ArrayList();
coll.add(123);
coll.add("ABC");
coll.add(new Object());
coll.add(true);
Iterator iterator = coll.iterator();
while(iterator.Next() != null){
System.out.println(iterator.next());
}
for(Object i:coll){
System.out.println(i);
}
}
方法二:通过增强for循环实现集合的遍历
public void testCollection2(){
Collection coll = new ArrayList();
coll.add(123);
coll.add("ABC");
coll.add(new Object());
coll.add(true);
for(Object i:coll){
System.out.println(i);
}
}
通过增强for循环实现数组的遍历
public void tesFor(){
String[] str = new String[]{"AA","SS","123"};
for(String s:str){
System.out.println(s);
}
}
4.Collection子接口:Set接口(存储元素无序,不可重复的集合)
-
添加进Set中的元素所在的类,一定要
重写equals()和hashCode()
方法 -
无序性:
无序性 != 随机性
(无序性是指元素在底层存放位置的无序) -
不可重复性:当向Set中添加相同的元素的时候,后面的元素不能添加进去
-
向Set中添加对象时,首先调用对象所在类的
hashCode()
方法,计算此对象的哈希值,哈希值决定对象存储位置。若对象要存储的位置没对象,就直接存储进去;若对象要存储的位置有对象,再通过equals()比较这两个对象是否相同(相同则后一个对象无法添加进来,反之则都存储)。
注:hashCode()方法与equals()方法需一致
HashSet(主要实现类)
例:
import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
public class Test{
@Test
public void testHashSet(){
Set set = new HashSet();
set.add(123);
set.add(456);
set.add(new String("AA"));
set.add("AA");
set.add(null);
System.out.println(set.size());
System.out.println(set);
}
}
LinkedHashSet
使用链表维护了添加进集合的顺序,当我们遍历此集合时,是按照添加的先后顺序进行遍历。
- LinkedHashSet插入性能低于HashSet,但在迭代访问却有很好的优势
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.Iterator;
import org.junit.Test;
public class Test11{
@Test
public void testHashSet(){
Set set = new LinkedHashSet();
set.add(123);
set.add(456);
set.add(new String("AA"));
set.add("AA");
set.add(null);//LinkedHashSet可以有null
//遍历集合
Iterator iterator = set.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
TreeSet
-
向TreeSet中添加的元素必须是同一类
-
可以按照添加进集合中的元素的指定的顺序遍历。如
String,包装类
等按照从小到大的顺序遍历 -
当自定义类没有实现
Comparable
接口时,当向TreeSet
中添加自定义类对象时,会报ClassCastException
的异常 -
向
TreeSet
中添加自定义类对象时有两种排序方式:自然排序和定制排序自然排序:要求自定义类实现
java.lang.Comparable
接口并重写其compareTo(Object obj)
方法-
compareTo()与hashCode()方法及equals()
方法三者保持一致 -
在此方法中,指明按照自定义类的哪个属性排序
-
向TreeSet中添加元素时,首先按照
compareTo()
进行比较,一但返回0,虽然两个对象的比较的属性值相同,但是程序会认为这两个对象是相同的,进而使后一个对象无法添加进来
定制排序:
compare()与hashCode()方法及equals()
方法三者保持一致- 详细案例见附件
-
5.Collection子接口:List接口(存储元素有序,可重复的集合)
添加进List中的元素所在的类,一定要 重写equals()
方法
ArrayList(主要的实现类)
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
public class Test10{
@Test
//List常用的方法:增(add(Object obj)),删(remove(int index))改(set(int index,Object obj))查(get(int index))插(add(int index,Object obj))长度(size())
//List相对于Collection的新增方法
public void test1(){
List list = new ArrayList();
list.add(123);
list.add(456);
list.add(789);
list.add(new String("ACA"));
list.add(new String("ACE"));
System.out.println(list);//[123, 456, 789, ACA, ACE]
//1.void add(int index,Object obj):在指定的索引位置添加元素
list.add(0,"SSS");
System.out.println(list);//[SSS, 123, 456, 789, ACA, ACE]
//2.Object get(int index):获取指定位置的元素
Object obj = list.get(3);
System.out.println(obj);//789
//3.boolean addAll(int index,Collection coll):判断向该集合中的指定位置加入集合coll;成功true,失败false;
List list1 = new ArrayList();
list1.add(1263);
list1.add(4566);
boolean b1 = list.addAll(1,list1);
System.out.println(b1);//true
System.out.println(list);//[SSS, 1263, 4566, 123, 456, 789, ACA, ACE]
//4.Object remove(int index):删除指定索引位置的元素
list.remove(0);
System.out.println(list);//[1263, 4566, 123, 456, 789, ACA, ACE]
//5.Object set(int index,Object obj):设置指定索引位置的元素为obj
list.set(0, 2222);
System.out.println(list);//[2222, 4566, 123, 456, 789, ACA, ACE]
//6.int indexOf(Object obj):返回第一次出现的指定元素obj在集合中的索引位置,没有返回 -1
int index = list.indexOf("ACE");
System.out.println(index);//6
//7.int indexOf(Object obj, intstartIndex):返回最后一次出现的指定元素obj在集合中的索引位置,没有返回 -1
System.out.println(list.lastIndexOf(123));//2
list.add(123);
System.out.println(list.lastIndexOf(123));//7
//8.List subList(int fromIdex,int toIndex):返回从fromIdex索引到 toIndex索引位置的集合元素{索引值不能为负,范围左闭右开(fromIdex,toIndex]}
List a1 = list.subList(2 ,8);
System.out.println(a1);//[123, 456, 789, ACA, ACE, 123]
}
}
LinkedList(对于频繁的插入,删除操作,则建议使用)
Vector(古老的实现类,线程安全,效率低于ArrayList)
练习
参考答案:略
6.Map接口(存储“键-值”对的数据)
- 用于保存具有映射关系的数据:
Key-Value
- Map中的key和value都可以是任何引用类型的数据
- Map中的key用Set来存放,不允许重复(value(用Collection存放)可以重复),所有的Entry(
Key-Value
对)是用Set存放,不可重复。同一个Map对象所对应的类,须重写hashCode()和equals()
方法 - 常用String类作为Map的"键"
- Key和Value之间存在单向一对一的关系,即通过指定的key都能找到唯一,确定的value
虚线实现,实线继承
HashMap(主要实现类)
向HashMap中添加元素时,会调用Key所在类的equals()
方法,判断两个Key是否相同,若相同,新老交替
(老的Entry被新的Entry覆盖)
Map的主要方法
public class TestMap{
@Test
public void test1(){
Map map = new HashMap();
//1.Object put(Object key,Object value):向Map中添加元素(即Entry:一对完整的键-值对)
map.put("AA", 223);
map.put("BB", 223);
map.put("AA", 227);
map.put(123, "cc");
map.put(null, null);
map.put(new Customer("OO", 33), 99);
map.put(new Customer("OO", 33), 99);
//2. int size():返回集合长度
System.out.println(map.size());//5(Key不可重复)
System.out.println(map);//{AA=227, BB=223, null=null, Customer [name= OO, id=33]=99, 123=cc}
//3.Object remove(Object key):按照指定的Key,删除对应的Entry
map.remove(123);
System.out.println(map);//{AA=227, BB=223, null=null, Customer [name= OO, id=33]=99}
//4.void putAll(Map t):将新的Map(t)添加进本map
Map map1 = new HashMap();
map1.put(111, 223);
map1.put(222, 223);
map.putAll(map1);
System.out.println(map);//{AA=227, BB=223, null=null, Customer [name= OO, id=33]=99, 222=223, 111=223}
//5.clear():清空
System.out.println(map1);//{222=223, 111=223}
map1.clear();
System.out.println(map1);//{}
//6.Object get(Object key):获取指定Key的Value值,若无此Key,就返回null
System.out.println(map.get(999));//null
//7.boolean containsKey(Object key):
boolean b1 = map.containsKey("AA");
System.out.println(b1);//ture
//8.boolean containsValue((Object Value):判断此集合中是否有值为Value的Entry,有返回ture,没有返回false;
boolean b2 = map.containsValue(227);//此时map中有一个值为227的Entry
System.out.println(b2);//ture
map.remove("AA", 227);
boolean b3 = map.containsValue(227);//此时map中没有值为227的Entry
System.out.println(b3);//false
//9.boolean isEmpty():判断集合是否为空
boolean b4 = map.isEmpty();
System.out.println(b4);//false
//10.boolean equals(Object obj):判断此集合是否完全等于集合obj(即判断本集合是否与obj集合是否一样)
map1.put("aa", 234);
map1.put("AA", 234);
boolean b5 = map.equals(map1);
System.out.println(b4);//false
}
}
Map的遍历
public class TestMap{
@Test
public void test2(){
Map map = new HashMap();
map.put("AA", 223);
map.put("BB", 223);
map.put(123, "cc");
map.put(null, null);
map.put(new Customer("OO", 33), 99);
//1.Set KeySet():遍历Key集
Set set = map.keySet();
for(Object obj : set){
System.out.println(obj);
}
//AA BB null Customer [name= OO, id=33] 123
//2.Collection values():遍历Value集
Collection coll = map.values();
Iterator i = coll.iterator();
while(i.hasNext()){
System.out.println(i.next());
}
//223 223 null 99 cc
//3.Set entrySet():遍历Key-Value集
Set entry = map.entrySet();
for(Object obj : entry){
//直接打印
System.out.println(obj);
//转变类型通过get方法遍历
Map.Entry entrily = (Map.Entry)obj;
System.out.println(entrily.getKey() + "=====>" + entrily.getValue());
}
//AA=223 BB=223 null=null Customer [name= OO, id=33]=99 123=cc
//4.通过遍历Key集进而遍历Value集
Set set1 = map.keySet();
for(Object obj : set1){
System.out.println(obj + "=====" + map.get(obj));
}
//AA=====223 BB=====223 null=====null Customer [name= OO, id=33]=====99 123=====cc
}
}
LinkedHashMap
使用链表维护添加进Map中的顺序,遍历时,按照添加的顺序遍历
public class TestMap{
@Test
public void test3(){
Map map = new LinkedHashMap();
map.put("AA", 223);
map.put("BB", 223);
map.put(123, "cc");
map.put(null, null);
map.put(new Customer("OO", 33), 99);
Set entry = map.entrySet();
for(Object obj : entry){
System.out.println(obj);
}
}
}
TreeMap
-
按照添加进Map中的元素的Key的指定属性进行排序,要求:key必须是同一类的对象
-
针对Key有自然排序与定制排序
-
自然排序(需重写
compareTo
方法)
例:
public class Customer implements Comparable{
private Integer id;
private String name;
public Integer getId(){
return id;
}
public void setId(Integer id){
this.id = id;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public Customer(String name,Integer id){
super();
this.name = name;
this.id = id;
}
public Customer(){
super();
}
@Override
public String toString(){
return "Customer [name= " + name + ", id=" + id + "]";
}
@Override
public int hashCode(){
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj){
if(this == obj)
return true;
if(obj == null)
return false;
if(getClass() != obj.getClass())
return false;
Customer other = (Customer)obj;
if(id == null){
if(other.id != null)
return false;
}else if(!id.equals(other.id))
return false;
if(name == null){
if(other.name != null)
return false;
}else if(!name.equals(other.name))
return false;
return true;
}
@Override
public int compareTo(Object o){//先按ID,后按名字排序
if(o instanceof Customer){
Customer c = (Customer)o;
int i = this.id.compareTo(c.id);
if(i == 0){
return this.name.compareTo(c.name);
}else{
return i;
}
}
return 0;
}
}
javapublic void test1(){
@Test
public void test4(){
Map map = new TreeMap();
map.put(new Customer("AA", 33), 99);
map.put(new Customer("BB", 39), 95);
map.put(new Customer("OO", 133), 69);
Set entry = map.entrySet();
for(Object obj : entry){
System.out.println(obj);
}
}
}
- 定制排序
例:
public void test2(){
@Test
public void test5(){
Comparator com = new Comparator(){
public int compare(Object o1,Object o2){
if(o1 instanceof Customer && o2 instanceof Customer){
Customer c1 = (Customer)o1;
Customer c2 = (Customer)o2;
int i = c1.getId().compareTo(c2.getId());
if(i == 0){
return c1.getName().compareTo(c2.getName());
}
return i;
}
return 0;
}
};
TreeMap map = new TreeMap(com);
map.put(new Customer("BB", 1001), 89);
map.put(new Customer("CB", 1001), 89);
map.put(new Customer("BB", 1011), 89);
map.put(new Customer("BB", 10101), 89);
Set entry = map.entrySet();
for(Object obj : entry){
System.out.println(obj);
}
}
}
Hashtable(子类:Properties)
-
线程安全
-
不允许使用null作为Key和Value
-
不保证其中
Key-Value
对的顺序 -
判断两个Key相同,两个value相同的标准与hashMap(通过
hashCode()方法及equals()方法
)一致 -
Properties常用来处理属性文件,键值都为
String
类型
例:
public void test2(){
@Test
public void test6() throws FileNotFoundException,IOException{
Properties pros = new Properties();
/*手动创建jdbc.sql文件
* user=root
* password=123ch
*/
//读取文件jdbc.sql
pros.load(new FileInputStream(new File("jdbc.sql")));
String user = pros.getProperty("user");
System.out.println(user);//root
String password = pros.getProperty("password");
System.out.println(user);//123ch
}
}
7.Collections工具类
- 用于操作Collection及Map的工具类
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.junit.Test;
public class Test18{
@Test
//排序操作:均为static方法
public void test1(){
List list = new ArrayList();
list.add(123);
list.add(345);
list.add(567);
list.add(789);
list.add(999);
System.out.println(list);//[123, 345, 567, 789, 999]
//1.reverse(List):反转List中元素的顺序
Collections.reverse(list);
System.out.println(list);//[999, 789, 567, 345, 123]
//2.shuffle(List):对List集合元素进行随机排序
Collections.shuffle(list);
System.out.println(list);//[567, 789, 345, 123, 999]
//3.sort(List)根据元素的自然顺序对指定List集合元素按升序排序
Collections.sort(list);
System.out.println(list);//[123, 345, 567, 789, 999]
//4.sort(List,Comparator)根据指定的Comparator产生的顺序对List集合元素进行排序(可略过)
ArrayList<Customer> list1= new ArrayList<>();
list1.add(new Customer("rank",20));
list1.add(new Customer("Jack",16));
list1.add(new Customer("Tom",18));
Collections.sort(list1, new Comparator<Customer>() {
@Override
public int compare(Customer o1, Customer o2) {
return o1.getId()-o2.getId(); //根据id进行升序排序
}
});
System.out.println(list1);
//5.将指定List集合的i处元素和j处元素进行交换
Collections.swap(list, 0, 3);
System.out.println(list);//[789, 345, 567, 123, 999]
}
@Test
//查找,替换操作
public void test2(){
List list = new ArrayList();
list.add(123);
list.add(345);
list.add(567);
list.add(789);
list.add(999);
list.add(789);
System.out.println(list);//[123, 345, 567, 789, 999]
//1.Object max(Collecton):根据元素的自然顺序,返回集合中的最大元素
System.out.println(Collections.max(list));//999
//2.Object min(Collecton):根据元素的自然顺序,返回集合中最小元素
System.out.println(Collections.min(list));//123
//3.int min(Collecton,Object):返回指定集合中指定元素的出现次数
int i = Collections.frequency(list, 789);
System.out.println(i);//2
//4.void copy(List desc,List src):将src中的元素复制到desc中(注:需要desc元素长度大于等于src元素长度,并且复制的元素会覆盖desc元素的src元素相应长度的位置,desc元素长度不变)
List list1 = new ArrayList();
list1.add("AAA");
list1.add("BBB");
Collections.copy(list, list1);
System.out.println(list);//[AAA, BBB, 567, 789, 999, 789]
//5.boolean replaceAll(List list,Object oldValue,Object newValue):使新值替换List中对应的旧值
boolean b1 = Collections.replaceAll(list, 999, 111);
System.out.println(b1);//true
System.out.println(list);//[AAA, BBB, 567, 789, 111, 789]
//同步控制
//将指定集合包装线程同步的集合,进而解决多线程并发访问集合时的线程安全问题
List list3 = Collections.synchronizedList(list);
System.out.println(list3);
}
}
练习
参考答案:略
感谢大家的支持,关注,评论,点赞!
参考资料:
尚硅谷宋红康20天搞定Java基础中部