一.集合简介
1.概念
集合就是用来储存数据,储存多个数据,动态的扩张长度,弥补了数组固定大小的缺陷。
2.存储结构
(a)顺序结构:将集合中的元素依次放在某个区域,在内存中是连续的分配空间
特点:访问效率高,插入和删除效率低
(b)链式结构/链表:在内存中分配的空间不是连续的
分为:单向链式/双向链式
特点:插入和删除效率高,访问效率低
3.集合框架(接口和类)
集合相关的接口和类 -- java.util包
(1)Collection 接口
(a)List接口 顺序,可重复的
ArrayList
LinkedList
Vector
Stack
(b)Set接口 无序,不可重复
HashSet
TreeSet
(2)Map接口,键值对
(a)HashMap
(b)HashTable
Properties
二.List接口
特点: 有序,可重复
1.ArrayList 基本方法
特点: 实现了长度可变的数组
* 本质上就是数组实现的,数组的默认长度为10
* 特点:顺序结构进行存储
* 访问效率高,插入和删除效率低,后面的所有元素会移动
例如:ArrayList<String> strlist=new ArrayList<String>();
增add;向指定的索引位置,添加从0开始
删除数据/删remove 索引位置的元素 返回的是被删除的元素
改set 返回的String类型被修改的值
查 get获取指定索引位置的元素
size()集合的大小
isEmpty()是否为空
indexOf指定元素在集合中的索引 找不到 -1
lastIndexOf 最后一次出现处的索引 没有则返回-1
contains():是否包含该元素
clear()清空集合
toArray() 集合--->数组(可以用数组特有的方法)
Arrays.asList数组--->集合;泛型必须是包装类类型,而不能是基本类型(包括基本类型的数组)
2.ArrayList常用方法
ArrayList list1 = new ArrayList(); 不指定泛型时,可以写入任何类型的数据
在集合中放入对象时 会自动转为Object类型;instanceof判断是否为后面这个类
每次要单独判断很麻烦 集合要加上泛型 ArrayList<Dog>doglist=new ArrayList<Dog >();
ArrayList list2 = new ArrayList();
Chinese chinese = new Chinese("语文");
English english = new English("英语");
list2.add(chinese);
list2.add(english);
for(Object o:list2){
if(o instanceof Chinese){
Chinese a=(Chinese) o;
System.out.println("Chinese的名字是:"+a.getName());
}else{
English b=(English) o;
System.out.println("English的名字是:"+b.getName());
}
}
3.集合的遍历
List<String> asList = Arrays.asList("aa","bb","cc");
(1)方法一 for循环
for (int i = 0; i < asList.size(); i++) {
System.out.print(asList.get(i)+"\t");
}
(2)方法二 foreach循环
for(String a:asList){
System.out.print(a+"\t");
}
(3)方法三 集合是可以被迭代的,迭代器主要继承了迭代器Iterable类,表示当前类可以被迭代
获取一个迭代器对象,本身就是继承下来的 不需要new 直接用
interface List<E> extends Collection<E> 且interface Collection<E> extends Iterable<E>
Iterator<String> i= asList.iterator();
while(i.hasNext()){ //判断集合是否有下一个元素
String next = i.next();//获取next值并输出
System.out.print(next+"\t");
}
4.ArrayList练习
public class Arraylist集合练习 {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
List<Integer> intlist=new ArrayList<Integer>();
while(true){
System.out.println("请输入整数(输入0表示结束):");
int next=input.nextInt();
if(next==0)
break;
else
intlist.add(next);
}
System.out.println("输入结束啦");
// 字符串和集合一样 有顺序 删掉一个后数组下标前移 所以需要倒着删
for (int i = intlist.size()-1; i >=0; i--) {
int num=intlist.get(i);//数组是有下标的 集合需要get获得
if(num%3==0){
intlist.remove(i);//或者 intlist.remove(num)
}
}
System.out.println(intlist);
/*
foreach没有下标 是对每个元素进行遍历
报错ConcurrentModificationException foreach循环时不能对集合直接进行remove
for(Integer i:intlist){
if(i%3==0){
intlist.remove(i);
}
System.out.print(i+"\t");
}*/
// 迭代器本身有remove()方法 可以删除当前迭代的元素
Iterator<Integer> it = intlist.iterator();
while(it.hasNext()){
int next=it.next();
if(next%3==0){
// intlist.remove(next);会报错 不能一边遍历一边删除
it.remove();
}
}
System.out.println(intlist);
}
}
5.LinkedList
存储结构:双向链式
特点: 插入和删除效率高,查询低
常用:List中的所有方法,具有几个额外的方法
6.Vector
vector 和ArrayList 相似,都是使用数组实现,用法基本相同
vector:
线程安全的
效率低,影响性能
Iterator或者Enumeration遍历 (比较老)
已经过时,不建议使用
Arraylist
线程不安全
效率高
不能使用Enumeration遍历
Stack
stack 继承了vector
特点:先进后出
Vector<String> v= new Vector<String>();
v.add("aa");
v.add("bb");
v.add("cc");
// 使用枚举法前先获取枚举法 后序遍历和迭代器一样
Enumeration<String> elements = v.elements();
while(elements.hasMoreElements()){
String nextElement = elements.nextElement();//下一个值保存下来用
System.out.println(nextElement);
}
7.性能测试ArrayList和LinkedLis
ArrayList<Integer> arrayList = new ArrayList<Integer>();
LinkedList<Integer> linkedList = new LinkedList<Integer>();
long past1= System.currentTimeMillis();
for (int i = 0; i <100000; i++) {
arrayList.add(0, 10);
}
long now1= System.currentTimeMillis();
System.out.println("ArrayList所用时间是:"+(now1-past1));
long past2= System.currentTimeMillis();
for (int i = 0; i <100000; i++) {
linkedList.addFirst(10);
}
long now2= System.currentTimeMillis();
System.out.println("LinkedList所用时间是:"+(now2-past2));
同StringBuffer和StringBuild测试速度,linkedlist速度比ArrayList更快
arrayList默认都往末尾添加 没办法造成别的元素的移动 循环插入第一个
三.set接口
特点:
* 无序(元素顺序与放入时无关),不能按照索引访问。
* 不可重复的(集合中不允许出现重复的元素)
实现类: HashSet TreeSet
1.HashSet
HashSet是一种哈希算法的集合,以哈希表的形式存储
数据结构:哈希表,散列表
特点:操作速度很快,效率高(根据HashCode()方法的返回值,确定存放的位置)
HashSet判断元素重复的过程:
1.添加元素时,首先调用要存入对象的hashCode()方法,获取hashCode值
2.根据hash值,使用哈希算法,获取哈希表中的存放位置
3.怎么判断该为位置是否有元素
如果该位置没有元素,就直接放入
如果该位置已经用元素,就调用对象的equals方法进行比较
返回true,元素重复的,舍弃当前要要放入的元素
返回false,则在当前位置下,以链表的形式追加 ---- 破坏了当前数据结构,影响哈希表性能。
当hashcode值相同而equals不同 会以链表的形式 放在地址下面
总结:
(1)HashSet判断元素的依据:两个元素hashCode值相同,equals比较为true---- 重复元素
(2)向set集合中添加元素时,需要重新hashCode()和equals()方法,防止相同的元素被添加到集合中。
Test01():相同的元素不会添加到集合中
add一个值 获取其hashcode值 放到hash表中相应的存储位置
set集合不能通过get获取值 因为标索引的是链表list
常用方法:add size isEmpty remove contains toArray iterator clear
Test02(): stu1和stu2获取的是hash值 默认返回地址 两个不同的地址 计算出两个不同存放位置;
用处:录入学号时(独一无二)有重复 系统提醒
public static void Test01() {
HashSet<String> hashSet = new HashSet<String>();
hashSet.add("aaa");
hashSet.add("bbb");
hashSet.add("ccc");
hashSet.add("ccc");
System.out.println(hashSet);
}
public static void Test02(){
HashSet<Stu> stu= new HashSet<Stu>();
Stu stu1=new Stu("Nancy",01);
Stu stu2=new Stu("Namcy",02);
stu.add(stu1);
stu.add(stu2);
System.out.println(stu);
}
2.HashSet与List的转换
List<String> asList = Arrays.asList("a","b","c");//数组直接转化为List 并赋值
/* List————>hashset可以实现去重
addAll()方法里面放一个Collection的接口 可以实现转化*/
HashSet<String> hashSet = new HashSet<String>();
hashSet.addAll(asList);
System.out.println(hashSet);
// hashSet—————>List
ArrayList<String> arr= new ArrayList<String>();
arr.addAll(hashSet);
arr.addAll(1, hashSet);//在索引为1处进行添加
System.out.println(arr);
3.TreeSet
TreeSet是用于对元素进行排序的有序集合类,不允许重复,不保证放入的顺序与输出的顺序一致
数据结构:二叉树
特点:元素有大写的顺序
TreeSet中对对象进行排序:
1. 让放的元素成为可比较的对象 ---- 该元素 实现 Comparable 接口 , 重写compareTo()方法。
2. 提供一个比较器,根据比较器进行比较
3. 定义一个比较器类,实现Comparator 接口,重写compare()方法
在Treeset创建出来时,将比较器类的对象传入。
总结:
TreeSet判断重复时:当添加的两个元素的compareTo()返回0时,则认为元素相同
/*报错:User cannot be cast to java.lang.Comparable
方法一:需要直接在类中添加Comparable接口*/
TreeSet<User> t2 = new TreeSet<User>();
t2.add(new User("Nancy",11));
t2.add(new User("Anta",11));
t2.add(new User("Lucky",2));
System.out.println(t2);
// 定义一个比较器类Mycompare,实现Comparator 接口,重写compare()方法
// 方法二:在Treeset创建出来时,将比较器类的对象传入。new对象即可
TreeSet<User> t3 = new TreeSet<User>(new Mycompare());
t3.add(new User("Nancy",22));
t3.add(new User("Anta",222));
t3.add(new User("Lucky",2));
System.out.println(t3);
// 方法三: 直接创建一个接口 保证实现接口中定义的方法后 new成功
// 匿名内部类:在Treeset创建出来时,将比较器类的接口传入(不需要再单独创建对象)
Comparator<User> comparator = new Comparator<User>() {
@Override
public int compare(User u1, User u2) {
if(u1.getAge()>u2.getAge()){
return 1;
}else if(u1.getAge()<u2.getAge()){
return -1;
}
else return 0;
}
};
TreeSet<User> t4 = new TreeSet<User>(comparator);
t4.add(new User("Nancy",22));
t4.add(new User("Anta",222));
t4.add(new User("Lucky",2));
System.out.println(t4);
//和谁比就把谁传进来 重写接口中的方法
public class User implements Comparable<User>{
/*自定义如何排序
升序:如果该对象大于指定对象返回正整数 小于返回负整数 等于返回0
降序:反之*/
@Override
public int compareTo(User o) {
if(this.age>o.getAge()){
return 1;
}else if(this.age<o.getAge()){
return -1;
}else {
return this.name.compareTo(o.getName());
// 字符串有特定比较方式 调用compareTo()方法即可
}
}
}
public class Mycompare implements Comparator<User>{
@Override
public int compare(User u1, User u2) {}
}
四.Map
Map集合用来处理键值对的映射关系,可以根据key键 操作对应的value值
(1)一种映射关系,key -- value 键 - 值
(2)key是唯一的,value可以重复
(3)无序的,不能按照索引访问元素
实现类: HashMap HashTable Properties
1.HashMap基本方法
基于哈希算法的map集合,以哈希表的结构存储数据,查找元素时效率高remove()删 返回被删除的key对应的value
get()查 根据key获取value值
keySet() 查所有
values()查所有
isEmpty()判断是否为空 size()元素个数 clear()清空
2.遍历HashMap
(1)通过keySet()获取所有的key集合,遍历key,通过key获取value
(2)通过values()获取所有value的集合,遍历value
(3)通过entrySet()获取所有的key-value的集合,然后分别得到key 和value
// 遍历hashMap中的所有key值
Set<String> keySet = hashMap.keySet();
for(String k :keySet){
System.out.print(hashMap.get(k)+" ");
}
System.out.println("\n");
// 遍历hashMap中的所有values值
Collection<Integer> values = hashMap.values();
for(Integer v:values){
System.out.print(v+" ");
}
System.out.println("\n");
// 方法一:entrySet遍历hashMap中的所有key————values
// enteySet() key=values 键值对的形式保存
// Set保存多个entry对象————保存多个键值对
Set<Entry<String, Integer>> entrySet = hashMap.entrySet();
for(Entry<String, Integer> entry:entrySet){
System.out.println("entry键值对形式:"+entry);
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
// 方法二:用迭代器方法遍历Set
Iterator<Entry<String, Integer>> iterator = entrySet.iterator();
while(iterator.hasNext()){
Entry<String, Integer> next = iterator.next();//得到的是键值对形式
System.out.println(next);
}
3.HashTable
遍历Hashmap与遍历Hashtable方法有一致的:keySet() values() entrySet() ;
HashTable独特遍历方法 枚举遍历(与Vector同)
// 先获取所有key的枚举实例
Enumeration<Integer> keys = hashtable.keys();
while(keys.hasMoreElements()){
Integer key= keys.nextElement();
System.out.println("获取到的key值:"+key+"\n"+"得到的value值:"+hashtable.get(key));
}
hashtable和hashmap用法基本一致
Hashtable:
线程安全 同步
key和value都不为null
enumeration遍历
HashMap:
线程不安全 异步
key和value都可以为null
不能用enumeration
4.Properties
Properties还是放key-value, 继承HashTable
属性文件以.properties为扩展名
数据格式: 属性名=属性值 (key=value)
只支持ISO-8859-1字符集,eclipse会将中文自动转码
public static void text01() {
Properties p= new Properties();
p.put(1, "abandon");
p.get(1);
// 设置属性 都需填字符串
p.setProperty("11", "Nancy");
System.out.println(p.getProperty("11"));
// 遍历:p.keys() p.values() p.entrySet()
}
public static void text02() throws IOException{
Properties p = new Properties();
// 加载到指定文件 固定写法
InputStream is=PropertiesTest.class//获取当前类的Class对象
.getClassLoader()//获得类加载器
.getResourceAsStream("date.properties");//获得指定路径下的文件
p.load(is);
System.out.println(p);
Set<Object> key= p.keySet();
for (Object o : key) {
// System.out.println(p.get(o));
System.out.println(o+p.getProperty((String)o));
}
}
五.Collections
1.Collections简介
Collections工具类提供了集合操作的相关的方法,如排序,查找,求最大值,最小值等
类似于Arrays工具类 工具类的方法都是静态的 直接.调用Collections里面的静态方法
2.Collections基本方法
ArrayList<Integer> list= new ArrayList<Integer>();
// 添加addAll()
Collections.addAll(list, 111,896,20);
System.out.println(list);
// max()和min()
System.out.println(Collections.max(list));
System.out.println(Collections.min(list));
// 反转swap()
Collections.swap(list, 0, list.size()-1);
// 反转reverse()
Collections.reverse(list);
// fill()填充
// Collections.fill(list, 0);
// sort()按照顺序 默认升序
Collections.sort(list);
System.out.println(list);
自定义排序:1(交换位置) -1(不动) 0(相等)
ArrayList<User> a = new ArrayList<User>();
a.add(new User("Nancy",22));
a.add(new User("Anta",222));
a.add(new User("Lucky",2));
System.out.println(a);
Collections.sort(a, new Comparator<User>() {
方法1-----降序排序
@Override
public int compare(User o1, User o2) {
if(o1.getAge()>o2.getAge()){
return -1;
}else if(o1.getAge()<o2.getAge()){
return 1;
}else{
return 0;
}
}
});
简单:return o2.getAge()-o1.getAge();
方法2----如果比较多个则:
int i=o2.getAge()-o1.getAge();
if(i==0){
return o2.getScore()-o1.getScore();
}
方法3-----可以在类定义的时候public class User implements Comparable<User>{进去定义}
这是一边看视频一边学习的笔记-借用了部分老师的笔记内容-如有侵权,通知删除!
新手小白学习之路~~~