1. 数据结构
栈(先进后出)
队列(先进先出)
数组(查询快,增删慢)
查询快:数组的地址是连续的,通过数组的首地址可以找到数组,通过数组的索引可以快速查找某一个元素
增删慢:数组的长度是固定的,增加或者删除,必须创建一个新数组,把数据源中的数据复制过来
链表(查询慢,增删快)
查询慢:链表中的地址不是连续的,每次查询的时候必须从头开始
增删快:增加或者删除对链表的整体结构是没有影响的
链表的结构
自己的地址------数据------下一个节点的地址
**单向链表:**只有一条链子,不能保证元素的顺序
**双向链表:**链表有两条链子,有一条链子是专门记录元素的顺序,是一个有序的集合
红黑树
**二叉树:**分支不能超过两个
**排序树/查找树:**在二叉数的基础上,元素是有大小顺序的。左子树小;右子树大;
**平衡树:**左孩子和右孩子数量相等
**不平衡树:**左孩子和右孩子数量不相等
红黑树:趋近于平衡树,查询速度非常快,查询叶子节点最大次数和最小次数不能超过2倍
约束:1.节点是红色的或者黑色的
2.根节点是黑色的
3.叶子节点(空节点)是黑色的
4.每个红色的节点的子节点都是黑色的
5.任何一个节点到其每一个叶子节点的所有路径上的黑色节点数相同
2. list
1.有序的集合,存储元素和取出元素的顺序是一致的
2.有索引,包含了一些带索引的方法
3.允许存储重复的元素
list接口中带索引的方法(特有的) 防止越界
// 创建一个list集合对象,多态
List<String> list = new ArrayList<String>();
// add方法添加元素
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
// 打印集合
System.out.println(list); // 不是地址,重写了tostring方法
//增加
list.add(3, "eee");
System.out.println(list);
//移除
String eString = list.remove(2);
System.out.println("被删的:"+eString);
System.out.println(list);
//替换
String rString=list.set(2, "wwww");
System.out.println("替换的:"+rString);
System.out.println(list);
//获取
for (int i = 0; i < list.size(); i++) {
String string = list.get(i);
System.out.println(string);
}
System.out.println("==========2============");
//使用迭代器
Iterator<String> it =list.iterator();
while (it.hasNext()) {
String s = it.next();
System.out.println(s);
}
System.out.println("===========3===========");
//使用增强for
for (String s:list) {
System.out.println(s);
}
ArrayList集合 底层是数组结构 查询快
LinkList集合 底层是链表结构 增删快
public static void main(String[] args) {
show01();// 头尾添加
show02();// 输出头尾 清除
show03();// 移除
}
private static void show01() {
// 创建对象
LinkedList<String> linked = new LinkedList<>();
// 添加元素
linked.add("a");
linked.add("b");
linked.add("c");
System.out.println(linked);
// 开头插入
// linked.addFirst("www");
linked.push("www");
System.out.println(linked);
// 结尾插入
linked.addLast("com");
System.out.println(linked);
}
private static void show02() {
// 创建对象
LinkedList<String> linked = new LinkedList<>();
// 添加元素
linked.add("a");
linked.add("b");
linked.add("c");
System.out.println("=======2============");
linked.clear();
if (!linked.isEmpty()) {
String first = linked.getFirst();
String last = linked.getLast();
System.out.println(first);
System.out.println(last);
}
}
private static void show03() {
// 创建对象
LinkedList<String> linked = new LinkedList<>();
// 添加元素
linked.add("a");
linked.add("b");
linked.add("c");
System.out.println("=======3============");
//String a = linked.removeFirst();
String a = linked.pop();
String b = linked.removeLast();
System.out.println("第一个"+a);
System.out.println("最后一个"+b);
System.out.println(linked);
}
Vector集合 可以实现可增长的对象数组
3.set接口
set接口的特点
1.一个不包含重复元素
2.没有索引,没有带索引的方法,也不能使用普通的for循环遍历
Hashset特点:
1.无序的集合,存储元素和取出元素的顺序有可能不一致
2.底层是一个哈希表结构(查询速度快)
public static void main(String[] args) {
Set<Integer> set = new HashSet<>();
set.add(1);
set.add(3);
set.add(2);
set.add(1);
// 使用迭代器遍历set集合
Iterator<Integer> it = set.iterator();
while (it.hasNext()) {
Integer s = it.next();
System.out.println(s);
}
System.out.println("===========2===========");
// 使用增强for
for (Integer s : set) {
System.out.println(s);
}
}
哈希值:十进制整数,由系统随机给出(就是对象的地址值,是一个逻辑地址,是模拟出来得到地址,不是数据实际存储的物理地址),在object类有一个方法,可以获取对象的哈希值
hashcode方法的源码:public int hashcode();
哈希表结构(查询速度快)
jdk1.8版本之前,哈希表=数组+链表
jdk1.8版本之后,哈希表=数组+链表=数组+红黑树(提高查询的速度)初始容量是16
两个元素不同,但哈希值相同(重地,通话) 哈希冲突
set集合在调用add方法的时候,add方法会调用元素的hashcode方法和equals方法,判断元素是否重复
HashSet存储自定义类型元素,必须重写hashcode和equals方法
LinkedHashSet集合,底层是哈希表+链表(多了一条链表),保证元素有序
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("p2");
set.add("p1");
set.add("p1");
set.add("p3");
System.out.println(set);//无序不允许重复 [p1,p2,p3]
LinkedHashSet<String> linked=new LinkedHashSet<>();
linked.add("p2");
linked.add("p1");
linked.add("p1");
linked.add("p3");
System.out.println(linked);//有序的,不允许重复 [p2,p1,p3]
}
可变参数(方法类型确定,参数数量不确定,使用可变参数…)
1.一个方法的参数列表只能有1个可变参数
2.可变参数必须写在参数列表的末尾
4.Collections
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list,"2", "5", "2", "3","8","9");//添加多个元素
System.out.println(list);
Collections.shuffle(list);//打乱顺序
System.out.println(list);
Collections.sort(list);//默认排序,升序
System.out.println(list);
//自定义排序,需重写方法
Comparator和Comparable的区别
Comparator:自己(this)和别人(参数)比较,自己需要实现comparable接口,重写比较的规则compareTo方法
Comparable:相当于找一个第三方进行比较
o1-o1:升序
}
Collections.singletonList方法的使用
这个方法主要用于只有一个元素的优化,减少内存分配,无需分配额外的内存,可以从SingletonList内部类看得出来,由于只有一个element,因此可以做到内存分配最小化,
//普通写法
List<MyBean> beans= MyService.getInstance().queryBean(param);
if (CollectionUtils.isEmpty(beans)) {
beans= new ArrayList<>();
MyBean bean= new MyBean(param);
beans.add(bean);
}
//优化写法
List<MyBean> beans= MyService.getInstance().queryBean(param);
if (CollectionUtils.isEmpty(beans)) {
MyBean bean= new MyBean(param);
beans= Collections.singletonList(bean);
}
// 或者直接调用常量 EMPTY_LIST
public static final <T> List<T> emptyList();
方法返回的List是Collections类的一个静态内部类,它继承AbstractList后
并没有实现add()、remove()等方法,因此这个返回值List并不能增加删除元素。
这个方法主要目的就是返回一个不可变的列表,使用这个方法作为返回值
就不需要再创建一个新对象,可以减少内存开销。并且返回一个size为0
的List,调用者不需要校验返回值是否为null,所以建议使用这个方法
返回可能为空的List。
5.Map<K,Y>
特点:
1.双列集合,一个元素包含两个值(key,value)
2.key和value类型可以相同,也可以不同
3.key是不允许重复的,value是可以重复的
4.key和value是一一对应k5
HashMap集合
1.底层是哈希表,查询速度特别k
2.该集合是无序的集合
LinkedHashMap集合
1.底层是哈希表+链表
2.该集合是有序的集合
//空值返回null
public static void main(String[] args) {
// show01();
//show02();
//show03();
show04();
}
private static void show01() {
// TODO Auto-generated method stub
Map<String, String> map = new HashMap<>();
String v1 = map.put("a", "a1");
String v2 = map.put("a", "a2");
System.out.println("v1:" + v1);//null
System.out.println("v2:" + v2);//a1
System.out.println(map);//{a=a2}
map.put("b", "b1");
map.put("c", "c1");
map.put("d", "b1");
System.out.println(map);//{a=a2, b=b1, c=c1, d=b1}
}
private static void show02() {
// TODO Auto-generated method stub
Map<String, String> map = new HashMap<>();
map.put("a", "a1");
map.put("b", "b1");
map.put("c", "c1");
map.put("d", "b1");
System.out.println(map);//{a=a1, b=b1, c=c1, d=b1}
String v2 = map.remove("a");//a1
String v3 = map.remove("f");//null
System.out.println(v2);
System.out.println(v3);
System.out.println(map);//{b=b1, c=c1, d=b1}
}
private static void show03() {
// TODO Auto-generated method stub
Map<String, String> map = new HashMap<>();
map.put("a", "a1");
map.put("b", "b1");
map.put("c", "c1");
map.put("d", "b1");
System.out.println(map);//{a=a1, b=b1, c=c1, d=b1}
String v2 = map.get("a");//a1
String v3 = map.get("f");//null
System.out.println(v2);
System.out.println(v3);
System.out.println(map);
}
private static void show04() {
// TODO Auto-generated method stub
Map<String, String> map = new HashMap<>();
map.put("a", "a1");
map.put("b", "b1");
map.put("c", "c1");
map.put("d", "b1");
System.out.println(map);
boolean v2 = map.containsKey("a");//true
boolean v22 = map.containsKey("aa");//false
boolean v3 = map.containsValue("a1");//true
boolean v33 = map.containsValue("a11");//false
System.out.println(v2);
System.out.println(v22);
System.out.println(v3);
System.out.println(v33);
System.out.println(map);//{a=a1, b=b1, c=c1, d=b1}
}
Set keySet() 返回此映射中包含的键的Set视图
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("b", "b1");
map.put("c", "c1");
map.put("d", "b1");
Set<String> set = map.keySet();
// 使用迭代器
System.out.println("=======1keySet()============");//for增强遍历
Iterator<String> it = set.iterator();
while (it.hasNext()) {
String key = it.next();
String value = map.get(key);
System.out.println(key + "=" + value);
}
System.out.println("===================");//for增强遍历
for (String a : set) {
String value = map.get(a);
System.out.println(a + "=" + value);
}
System.out.println("=======2Entry键值对对象============");
Set<Map.Entry<String, String>> set1 = map.entrySet();
// 使用迭代器
Iterator<Map.Entry<String, String>> it1 = set1.iterator();
while (it1.hasNext()) {
Map.Entry<String, String> entry = it1.next();
String aString = entry.getKey();
String bString = entry.getValue();
System.out.println(aString+"="+bString);
}
}
Entry键值对对象
当map集合一创建,那么就会在map集合中创建一个entry对象,用来记录键与值(键值对对象,键与值的映射关系)
public K getKey(); //获取Entry对象中的键
public V getValue(); //获取Entry对象中的值
public Set<Map.Entry<K,V>> entrySet(); //获取到Map集合中所有的键值对对象的集合(Set集合)
HashMap存储自定义类型键值
LinkedHashMap
Hashtable键值都不能为空
计算一个字符串中每个字符出现的次数
public static void main(String[] args) {
//使用scanner,获取用户输入的字符串
Scanner sc = new Scanner(System.in);
System.out.println("输入字符串");
String str = sc.next();
//创建map集合,key为字符串中的字符,value是字符的个数
HashMap<Character, Integer> map = new HashMap<>();
//遍历字符串,获取每一个字符
for (char c : str.toCharArray()) {
//判断key是否存在
if (map.containsKey(c)) {
Integer value = map.get(c);
value++;
map.put(c, value);//新的value值存入
} else {//不存在,有之前存在的一个
map.put(c, 1);
}
}
//遍历输出
for (Character key : map.keySet()) {
//通过key获取value
Integer value = map.get(key);
System.out.println(key + "有" + value);
}
}
HashMap:线程不安全,速度快,允许放入空值
HashTable:线程安全,速度较慢,不允许放入空值