集合:
分为两类:一类是单个方式存储元素,这一类集合中超级父接口:java.util.Collection;一类是以键值对的方式存储元素,这一类集合中国超级父接口:java.util.Map
关于java.utils.Collection接口中常用的方法
-
collection中能存放什么元素?没有使用“泛型”之前,collection中可以存放Object的所有子类型;使用了“泛型”之后,collection中只能存放某个具体的类型。(集合中不能直接存放基本数据类型,也不能存java对象,只是存储java对象的内存地址)。
-
collection中常用的方法
- boolean add(Object e)向集合中添加元素
public static void f1(){ //创建一个集合对象 //Collection c= new Collection();//接口是抽象的,无法实例化 //多态 Collection c= new ArrayList(); c.add(1200);//自动装箱,实际上是放进去了一个java对象的内存地址 c.add(3.14);//自动装箱 c.add(new Object()); c.add(new Student()); c.add(true);//自动装箱 } class Student{ }
- int size()获取集合中元素的个数
System.out.println("集合中元素的个数是:"+c.size);//5
- void clear()清空集合
c.clear(); System.out.println("集合中元素的个数是:"+c.size);//0
- boolean contains(Object o)判断集合中是否包含元素o,包含返回true(它在底层怎么判断是否包含某个元素的?调用了equals方法进行对比,equals方法返回true,就表示包含这个元素)
c.add("hello"); c.add("world"); c.add("浩克"); c.add("绿巨人"); c.add(1); boolean flag = c.contains("绿巨人"); System.out.println(flag);//true boolean flag2 = c.contains("绿巨人2"); System.out.println(flag);//false System.out.println(c.contains(1));//true System.out.println("集合中元素的个数是:"+c.size);//5
- boolean remove(Object o)删除集合中某个元素(调用了equals方法进行对比)
c.remove(1); System.out.println("集合中元素的个数是:"+c.size);//4
- boolean isEmpty()判断该集合中元素的个数是否为空
System.out.println(c.isEptya());//false
- Object[] toArray()调用这个方法可以把集合转换成数组
Object[] objs = c.toArrary(); for(int i= 0;i<objs.length;i++){ //遍历数组 Object o=objs[i]; System.out.println(o); }
3.集合遍历/迭代器(集合结构发生变化,需要重新获取迭代器)删除集合中元素时,不能使用集合的对象调用removw()方法,应使用迭代器对象调用removw()方法,迭代器删除会自动更新迭代器,并跟新集合。
public static void f2(){ //以下的遍历方式/迭代方式,是所有Collection通用的一种方式 //在Map集合中不能用,在所有的Collection以及子类中使用 //创建集合对象 Collection c = new ArrayList(); //添加元素 c.add("abc"); c.add("def"); c.add(100); c.add(new Object()); //对集合COllection进行遍历 //第一步:获取集合对象的迭代器对象Iterator Iteartor it = c.iterator();//迭代器对象it最初并没有指向第一个元素 //第二步:通过以上获取的迭代器对象开始迭代 /* 以下两个方法是迭代器对象Iteartor中的方法: boolean hasNext()如果有元素可以迭代返回true Object next()返回迭代的下一个元素 */ boolean hasNext =it.hasNext(); while(hasNext){ //存进去是什么类型,取出来还是什么类型 Object obj = it.next(); //只不过在输出的时候会转成字符串,因为println会调用toString()方法 System.out.println(obj); } //HashSet集合 :无序不可重复 Collection c2 = new HashSet(); c2.add(100); c2.add(200); c2.add(300); c2.add(90); c2.add(400); c2.add(50); c2.add(60); c2.add(100); Iteartor it2 = c.iterator(); while(it2.hasNext){ System.out.println(it2.next()); } //400 50 100 200 90 300 60 }
List接口中常用的方法
对List集合中的元素排序,需要保证List集合中的元素实现了Comprarable接口
1.List集合存储元素特点:有序可重复
有序:List集合元素有下标
从0开始,以1递增
可重复:存储一个1,还可以再存储1
2.List既然是Collection接口的子接口,那么肯定List接口有自己“特色”的方法,以下只列出List接口特有的常用方法
void add(int index,Object element)
Object get(int idex)
int indexOf(Object 0)
Object remove(int index)
Object set(int index,Object element)
public static void f1(){
//创建list类型集合
//List myList = new LinkedList();
//List myList = new Vector();
List myList = new ArrayList();
//添加元素
myList.add("A");//默认向集合末尾添加
myList.add("B");
myList.add("C");
myList.add("C");
myList.add("D");
//第一个参数是下标,使用不多,效率低
myList.add(1,"KING");
//迭代
Iterator it = myList.iterator();
while(it.hasnext()){
Object elt = it.next();
System.out.println(elt);
}
//A
//KING
//B
//C
//D
//根据下标来取元素
Object firstObj= myList.get(0);
System.out.println(firstObj);
//因为有下标,所以List集合有自己比较特殊的遍历方式
//通过下标遍历,List集合特有,Set没有
for(int i;i < myList.size();i++){
Object obj = myList.get(i);
System.out.println(obj);
}
//获取指定对象第一次出现处的索引
System.out.println(myList.indexOf("C"));//3
//获取指定对象最后一次出现处的索引
System.out.println(myList.lastIndexOf("C"));//4
//删除指定下标位置的元素
//删除下标为0的元素
myList.remove(0);
System.out.println(myList.size());//5
//修改指定位置的元素
myList.set(2,"soft");
//遍历集合
for(int i = 0;i < myList.size();i++){
Object obj = myList.get(i);
System.out.println(obj);
}
//KING
//B
//soft
//C
//D
}
ArrayList类
1.默认初始化容量是10(底层先创建了一个长度为0的数字,当添加一个元素时,初始化容量是10)
2.集合底层是一个Object[]数组,相当于顺序表
3.构造方法:new ArrayList(); new ArrayList(20);
4.ArrayList集合的扩容:原容量的1.5倍。底层是数组,如何优化?尽可能少的扩容,建议使用ArrayList集合的时候预估计元素的个数,给定一个初始化容量。
5.数组优点:检索效率比较高;数组缺点:随机增删元素效率比较低,无法存储大数据量。向数组末尾添加元素,效率很高,不受影响。
6.面试:这么多集合中使用ArrayList最多
7.构造方法
public static void f3(){
//默认初始化容量10
List myList = new ArrayList();
//指定初始化容量100
List myList2 = New ArrayList(100);
//创建一个HashSet集合
Collection c = new HashSet();
c.add(100);
c.add(200);
c.add(900);
c.add(50);
//通过这个构造方法就可以将HashSet集合转换成List集合
List myList3 = new ArrayList(c);
for(int i=0;i < myList.size();i++){
System.out.println(myList.get(i));
}
//50
//100
//90
//50
}
LinkedList
底层是双向链表,若增删集合中元素较多时,使用LinkedList
public class LinkedListDemo {
//顺序表:便于查找 O(1) 增加删除移动元素O(n)
//链表:便于增删 O(1),查询O(n)
public static void main(String[] args) {
LinkedList<String> list=new LinkedList<String>();
list.addLast("aaa");
list.addFirst("bbb");
System.out.println(list);
//栈(先进后出 addLast入栈 removeLast出栈)和队列(先进先出addLast入队 removeFirst出队)
//iterator()从前往后 hasNext listIterator()从前往后hasNext,从后向前hasPrevious
Iterator<String> it= list.iterator();
while(it.hasNext()){
System.out.print(it.next()+ " ");
}
System.out.println(); //bbb aaa
ListIterator<String> listIt2=list.listIterator();
while(listIt2.hasNext()){
System.out.print(listIt2.next()+ " ");
}
System.out.println();//bbb aaa
ListIterator<String> listIt3=list.listIterator();
while(listIt3.hasPrevious()){
System.out.print(listIt3.previous()+ " ");
}
System.out.println();// 空的,没有值 ,从第一个开始向前,没有元素,所以为空
ListIterator<String> listIt4=list.listIterator(list.size());
while(listIt4.hasPrevious()){
System.out.print(listIt4.previous()+ " ");
}
System.out.println();//aaa bbb
}
}
泛型
private static void f1() {
//可以存放任意类型,但是后期处理数据会带来很多问题
ArrayList list1 = new ArrayList();
list1.add(10);
list1.add("张三");
list1.add(3.15);
//确定数据是String类型
ArrayList<String> list2 = new ArrayList<String>();
list2.add("张三");
ArrayList<Integer> list3 = new ArrayList<Integer>();
list3.add(10);
//list3.add("张三");//错误,只能存放integer类型
}
HashSet
初始化容量是16,初始化容量建议2倍,扩容之后是原容量的2倍。
public class HashSetDemo {
public static void main(String[] args) {
//线性表 ,有重复的,无序的
ArrayList<Integer> list=new ArrayList<Integer>() ;
list.add(1);
list.add(1);
System.out.println(list.size());//2
//集合中元素,没有重复的元素,元素是否有序(无序的,)
//但是HashSet是有序的,因为它借助HashMap,键值对操作,比较大小的过程
HashSet<Integer> set=new HashSet<Integer>();//导包 ctrl+shift+o
set.add(1);
set.add(1);
System.out.println(set.size());//1
set.add(3);
set.add(2);
Iterator<Integer> it=set.iterator();
while(it.hasNext()){
System.out.print(it.next()+" ");
}
System.out.println();//1 2 3
System.out.println(set);//[1, 2, 3]
}
}
public class HashSetDemo2 {
public static void main(String[] args) {
//f2();
//什么情况下,认为两个学生是同一个,默认情况下同一个对象
//我们想要这样认为::只要两个的学号相同,我们就认为是同一个,只存储一个
//集合中,添加元素,首先获取HashCode,如果哈希码不同,直接添加;哈希码相同的情况下,再比较Equals方法,当该方法返回真的时候,不再添加,直接舍去新值。
//取决于自定义类hashCode() equals方法的定义
f1(); //1
f11();//1
}
private static void f11() {
HashSet<Student> set=new HashSet<Student> ();
Student s1=new Student("001", "zhangsan");
Student s2=new Student("001", "lisi");
set.add(s1);
set.add(s2);
System.out.println(set.size());
System.out.println(set);//[Student [no=001, name=zhangsan]]
}
private static void f1() {
HashSet<Student> set=new HashSet<Student> ();
Student s1=new Student("001", "zhangsan");
Student s2=new Student("001", "zhangsan");
set.add(s1);
set.add(s2);
System.out.println(set.size());
}
private static void f2() {
HashSet<Student> set=new HashSet<Student> ();
Student s1=new Student("001", "zhangsan");
Student s2=s1;
set.add(s2);
set.add(s1);
System.out.println(set.size());//1
}
}
//学生类
public class Student {
String no,name;
public Student(String no, String name) {
super();
this.no = no;
this.name = name;
}
public Student() {
}
public String getNo() {
return no;
}
public void setNo(String no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int hashCode() {
return no.hashCode(); //只考虑学号,不考虑姓名
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;//地址
//if (obj == null) return false;//空值
//if (getClass() != obj.getClass())return false;//类型不同
Student other = (Student) obj;
if(no.equals(other.getNo())){
return true;
}
return false;
}
@Override
public String toString() {
return "Student [no=" + no + ", name=" + name + "]";
}
}
关于java.utils.Collection接口中常用的方法
1.Map和Collection没有继承关系。
2.Map集合以key和value的方式存储数据:键值对
key和value都是引用数据类型
key和value都是存储对象的内存地址
key起主导地位,value是key的一个附属品
3.Map接口中常用方法
V put(K key,V value) 向Map集合中添加键值对
V get(Object key)通过key获取value
void clear()清空Map集合
boolean containsKey(Object key)判断Map中是否包含某个key
boolean containsValue(Object value)判断Map中是否包含某个value
boolean isEmpty() 判断Map集合中 元素个数是否为0
Set keySet() 获取Map集合所有的key
V remove(Object key)通过key删除键值对
int size()获取Map集合中键值对的个数
Collection values()获取Map集合所有value,返回一个Collection
Set<Map.Entry<K,V>> entrySet() 将Map集合转换成Set集合
假设现在有一个Map集合,如下所示
map1集合对象
key value
1 zhangsan
2 lisi
3 wangwu
4 zhouliu
Set set = map1.entrySet();
set集合对象
1=zhangsan【注意:Map集合通过entrySet()方法转换成的这个Set集合,Set集合中元素的类型是Map.Entry<K,V>】
2=lisi【Map.Entry和String一样,都是一种类型的名字,只不过:Map>Entry是静态内部类,是Map中的静态内部类】
3=wangwu
4=zhouliu------->这个东西是什么?是Map.Entry
HashMap
在jdk8之后,如果哈希表单向链表中元素个数超过8个,单向链表这种数据结构会变成红黑树数据结构,当红黑树上的结点数量小于6时,会重新把红黑树变成单向链表数据结构。初始化容量16,默认加载因子75扩容是:扩容之后的容量是原容量的2倍。key和value值允许为空。
public class HashMapDemo1 {
//ArrayList LinkedList HashSet单列集合
//HashMap是双列集合,键值对集合
//商品管理,利用ArrayList实现,换用HashMap
public static void main(String[] args) {
HashMap<String,Goods> map=new HashMap<String,Goods>();
//1<<4 10000 16
Goods goods=new Goods("001", "苹果", 3.0);
map.put("001", goods);
goods=new Goods("002", "梨", 3.8);
//添加
map.put("002", goods);
goods=new Goods("003", "桃", 2);
//添加
map.put("003", goods);
goods=new Goods("004", "芒果", 2);
//添加
map.put("004", goods);
goods=new Goods("005", "葡萄", 4.5);
//添加
map.put("005", goods);
//查找,利用线性表实现的需要逐个比较,但是利用哈希表不需要比较
Goods goods2=map.get("001");
System.out.println(goods2);
//删除
//map.remove("001");
map.keySet();//键的集合
map.values();//值的集合
map.entrySet(); //键值对集合
//获取到键,通过键可以获取值
Set<String> set= map.keySet();
System.out.println(set); //[004, 005, 001, 002, 003]
for(String key:set){
System.out.print(key+"--->"+map.get(key)+", ");
}
System.out.println();//004--->004 芒果 2.0, 005--->005 葡萄 4.5
//只能输出值,不能获取到键
Collection<Goods> collection=map.values();
System.out.println(collection);
//[004 芒果 2.0, 005 葡萄 4.5, 001 苹果 3.0, 002 梨 3.8, 003 桃 2.0]
for(Goods goods22:collection){
System.out.println(goods22);
}
//键值对,获取到既有键又有值
Set< Entry<String,Goods> > set2= map.entrySet();
for(Entry<String,Goods> entry:set2){
System.out.println(entry.getKey()+"--->"+entry.getValue() );
}
}
}
properties
线程安全的,key和value只支持string类型,称为属性类。
public class PropertiesDemo{
//Property 属性 Properties 键值对集合 存储借助HashMap
public static void main(String[] args) throws IOException {
Properties props=new Properties();
//设置值的方法
props.put("color", "yello");
props.setProperty("字体", "宋体");
//获取值的方法
String s1=props.getProperty("color");
System.out.println(s1); //yello
String s2=props.getProperty("字号","无");//获取属性,没有的话用默认值
System.out.println(s2);//无
String s3=(String) props.get("字体");
System.out.println(s3);//宋体
props.list(System.out);//所有的属性显示到屏幕上
/*-- listing properties --
color=yello
字体=宋体*/
props.list(new PrintStream("aaa.txt") );//获取所有属性,并输出到文件中
//props.save(new FileOutputStream("bbb.txt"), "zhushi");//过时的 //获取所有属性,并输出到文件中
//props.store(new FileOutputStream("bbb.txt"), "zhushi"); //获取所有属性,并输出到文件中
props.load(new FileReader("bbb.txt"));
//装载的时候怎么,如果原属性有的话,覆盖,没有的话,新增
System.out.println(props);//{color=黄色, 字号=5, 字体=宋体}
}
}
TreeSet集合
1.底层实际 上是一个TreeMap
2.底层是一个二叉树
3.放到TreeSet集合中的元素,等同于放到TreeMap集合key部分了
4.集合中的元素:无序不可重复,但是可以按照元素的大小顺序自动排序
5.放在集合中的元素需要实现Comparable接口,并且实现compareTo方法,equals可以不写。
public static void f1(){
//创建一个TreeSet集合
TreeSet<String> ts = new TreeSet<>();
//添加Stirng
ts.add("zhangsan");
ts.add("lisi");
ts.add("wangwu");
ts.add("zhangsi");
ts.add("wangliu");
//遍历
for(Stirng s:ts){
System.out.println(s);
}
//按字典序排序
//lisi
//wangliu
//wangwu
//zhangsan
//zhangsi
}