文章目录
1.Set集合
Set:接口。数据唯一存储。无序。
1.1 HashSet
哈希值的存储方式:
hash的源码如下:
* 加载因子:
* static final float DEFAULT_LOAD_FACTOR = 0.75f;
* 二叉树阈值:
* static final int TREEIFY_THRESHOLD = 8;
* 数组的初始大小:
* static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("ab");//
set.add("ac");
set.add("ab");
//重复的无法add进set,但反着写ab虽hash值相同也可以添加成功
set.add("ba");
System.out.println(set);
//[ab, ac, ba]
}
实例:对于人物属性进行排序
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
class Student{
private int no;
private String name;
public Student(int no, String name) {
super();
this.no = no;
this.name = name;
}
public int getNo() {
return no;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Student [no=" + no + ", name=" + name + "]";
}
//此为自己设定的hash,不严谨
@Override
public int hashCode() {
return name.hashCode() + no;
}
@Override
public boolean equals(Object obj) {
// no + name 相同 就是同一个对象 this ,obj
Student stu = (Student)obj;
return this.no == stu.no && this.name.equals(stu.name);
}
//系统的hash,自动生成,严谨
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + no;
return result;
}
@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 (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (no != other.no)
return false;
return true;
}
}
public class TestHashSet2 {
public static void main(String[] args) {
Set<Student> set = new HashSet<>();
Student guojing = new Student(1, "郭靖");
Student yangkang = new Student(1, "郭靖");
Student huangrong = new Student(3, "黄蓉");
Collections.addAll(set, guojing,yangkang,huangrong);
set.forEach(System.out::println);
}
}
/*
Student [no=1, name=郭靖]
Student [no=3, name=黄蓉]
*/
1.2 TreeSet
树:由分支关系组成的层次结构。
二叉树:
实例:逆序输出
Set<Integer> set = new TreeSet<>((n1,n2)-> n2 - n1);
set.add(50);
set.add(45);
set.add(55);
System.out.println(set);
//[55, 50, 45]
实例:人物排序输出
import java.util.Collections;
import java.util.Set;
import java.util.TreeSet;
class Employee implements Comparable<Employee>{
private int no;
private String name;
private int age;
public Employee(int no, String name, int age) {
super();
this.no = no;
this.name = name;
this.age = age;
}
public int getNo() {
return no;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Employee [no=" + no + ", name=" + name + ", age=" + age + "]";
}
@Override
public int compareTo(Employee o) {
// return this.age - o.age;//年龄升序
int n = this.age - o.age;
if(n == 0) {
return this.no - o.no ;
}
return n;
}
}
public class TestTreeSet2 {
public static void main(String[] args) {
Set<Employee> set = new TreeSet<>();
Employee guojing = new Employee(1, "郭靖", 19);
Employee yangkang = new Employee(3, "杨康", 19);
Employee huangrong = new Employee(2, "黄蓉", 19);
Collections.addAll(set, guojing,yangkang,huangrong);
set.forEach(System.out::println);
}
}
/*
Employee [no=1, name=郭靖, age=19]
Employee [no=2, name=黄蓉, age=19]
Employee [no=3, name=杨康, age=19]
*/
1.3 区别
1.HashSet :
底层数据结构是 Hash表.
唯一。
无序。
效率高。
2.LinkedHahSet:
底层是链表。
唯一。
有序。
元素添加的顺序维护次序。
3.Treeset:
底层是 二叉树。
唯一。
有序。
自己定制顺序。
HashSet > LinkedHashSet > TreeSet
2.队列
队列:
访问受限的线性表。
添加元素 向队尾添加;
删除元素 只能从 队头移除。
先进 先出的数据结构。
//队列
Queue<String> q = new ArrayDeque<>();
Queue<String> q = new LinkedList<>();
// 入队:向队尾
// 添加成功返回true,失败异常
q.add("aa");
// 添加成功返回 true ,失败 false;
q.offer("bb");
q.offer("cc");
q.offer(null);//队列不允许添加 null值
//出队----------------------------------------------
// 返回移除的元素,删除失败引发异常
System.out.println(q.remove());// "aa"
// 返回移除的元素,删除失败返回null
System.out.println(q.poll());//
System.out.println(q.poll());*/
//---------------------------------------------------
//循环出队
while(q.size() > 0) {
System.out.println(q.poll());
}
3.Collections
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
// 向集合中 添加多个元素 :Collection
Collections.addAll(list, 22,11,33);
System.out.println(list);// [22, 11, 33]
// 1. 自然升序排序 List
Collections.sort(list);
System.out.println(list);//[11, 22, 33]
// 2. 定制顺序排序,List ,Comparator
Collections.sort(list, (n1,n2)->{return n2 -n1;});
System.out.println(list);// [33, 22, 11]
// 3. 前提 升序 排序 ,二分查找法 ,
System.out.println(Collections.binarySearch(list, 22));// 1
// 4. 返回集合中 最大的元素 Collection
System.out.println(Collections.max(list));// 33
// 5.返回集合中 最小的元素 Collection
System.out.println(Collections.min(list));//11
// 6. 反转集合中的元素: List
Collections.reverse(list);
System.out.println(list);//[33, 22, 11]
// 7. 返回 参数元素 在集合中出现的频率(次数) Collection
System.out.println(Collections.frequency(list, 33));// 1次
list.add(33);
list.add(33);
System.out.println(list);//[33, 22, 11, 33, 33]
System.out.println(Collections.frequency(list, 33));//3次
// 8.用第二个参数元素 替换掉集合中的所有元素,List
Collections.fill(list, 999);
System.out.println(list);//[999, 999, 999, 999, 999]
}
4.Map
Map:映射。双列存储。一对信息。 键值对。键是唯一的,值可以重复。
常用方法:
Map<Integer,String> map = new HashMap<>();
System.out.println(map.isEmpty());//true
// 添加
map.put(11, "aa");
map.put(22, "bb");
map.put(33, "cc");
System.out.println(map);
// 1. 集合中的键值对的数目
System.out.println(map.size());// 3
// 2. 集合是空的 true
System.out.println(map.isEmpty());// false
// 3. 返回 指定的键 在集合中是否包含
System.out.println(map.containsKey(22));// true
// 4. 返回 指定的 值 在集合中 是否包含,包含true
System.out.println(map.containsValue("cc"));//true
// 5. 按照指定的键 删除 集合中的键值对信息。
map.remove(22);
System.out.println(map);// {33=cc, 11=aa}
// 6. 键的集合Set
System.out.println(map.keySet());// [33, 11]
// 7. 值的集合Collection
System.out.println(map.values());// [cc, aa]
// 8.清除
map.clear();
System.out.println(map.size());// 0
遍历:
// 遍历
Map<Integer,String> map = new HashMap<>();
map.put(11, "aa");
map.put(22, "bb");
System.out.println(map);// {22=bb, 11=aa}
//-------------------遍历输出----------------------------
// 1. 集合的foreatch方法
map.keySet().forEach(System.out::println);
map.values().forEach(System.out::println);
map.forEach(new BiConsumer<Integer,String>() {
@Override
public void accept(Integer t, String u) {
System.out.println(t + "," + u);
}
});
map.forEach((k,v)-> {System.out.println(k + ":" + v);});
// 2.迭代器------------------------------------------------------------------
System.out.println("------------------------------------");
map.keySet().iterator().forEachRemaining(System.out::println);
map.values().iterator().forEachRemaining(System.out::println);
//Entry遍历
map.entrySet().forEach(e -> {System.out.println(e.getKey() + "," + e.getValue());});
// 键值对的集合
System.out.println("-------------Entry---------------------------");
Set<Entry<Integer,String>> set = map.entrySet();
Iterator<Entry<Integer,String>> i = set.iterator();// 获得 set的迭代器
while(i.hasNext()) {
System.out.println(i.next());//完整输出
Entry<Integer,String> e = i.next();
System.out.println("键:" + e.getKey());//键输出
System.out.println("值:" + e.getValue());//值输出
}
总结:
1.HashMap:底层哈希表。
键唯一的,无序。
可以存储null键 和 null值。
Hashtable: 线程安全的,性能低。
2.LinkedHashMap:底层是链表。
键唯一,有序。
键会按照 元素 添加的顺序维护 键值对的信息。
3.TreeMap:底层二叉树.
键是唯一的,可以定制顺序。
对键 定制顺序Comparator.
5.文件
File类:文件和目录的封装。
5.1 文件
//File f:\data\a.txt
// 构造(1)
File f = new File("f:\\data\\a.txt");//写法一
File f = new File("f:/data/a.txt");// 绝对路径,写法二
File f = new File("a.txt");//相对路径
// 构造(2)
File f = new File("f:/data","a.txt");
// 构造 (3)
File ff = new File("f:/data");
File f = new File(ff,"a.txt");
// 1. * 返回的是 文件 是否存在,存在 true
System.out.println(f.exists());// false
// 2. 新建文件
f.createNewFile();
System.out.println(f.exists());
// 3. 获得文件的名称
System.out.println(f.getName());// a.txt
// 4. 获得路径
System.out.println(f.getPath());// f:\data\a.txt
// 5. 获得绝对路径
System.out.println(f.getAbsolutePath());// f:\data\a.txt
// 6. 获得父路径
System.out.println(f.getParent());//f:\data
// 7. 可读,true
System.out.println(f.canRead());// true
// 8. 可写,true
System.out.println(f.canWrite());// true
// 9 . * 是否是文件
System.out.println(f.isFile());//true
// 10 .文件最后修改的时间
System.out.println(f.lastModified());// 毫秒
Date date = new Date(f.lastModified());
System.out.println(date);
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
System.out.println(format.format(date));// 2019-07-15 05:30:28.222
// 11 * 文件的长度:文件内容的字节数
System.out.println(f.length());// long
// 12. 删除文件
f.delete();
System.out.println(f.exists());//false
6.编写:HashSet 产生7个不重复的随机数
import java.util.HashSet;
public class TestHashSet3_exam {
public static void main(String[] args) {
Set<Integer> set = new HashSet<>();
int r;
while(true) {
r = (int)(Math.random()*(30-1+1) + 1);
set.add(r);
if(set.size() == 7)
break;
}
System.out.println(set);
}
}
7.编写:Map
import java.util.HashMap;
import java.util.Map;
public class TestMap4_exam {
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
map.put("PBC", "农业银行");
map.put("BC", "中国银行");
map.put("CBC", "建设银行");
map.put("ICBC", "工商银行");
//中文简称
map.keySet().forEach(System.out::println);
//英文全名
map.values().forEach(System.out::println);
//键值对
map.forEach((k,v)->{System.out.println(k+"="+v);});
// BC对应的银行
System.out.println(map.get("BC"));
// 一共几组
System.out.println(map.size());
//map包含BC吗
map.remove("BC");
System.out.println(map.containsKey("BC"));
//键值对
map.entrySet().iterator().forEachRemaining(System.out::println);
}
}
8.注意
1.Collection是最上层的接口,存储的数据是可以重复的
2.list数据可以重复,有顺序的线性排列
3.我们需要频繁查询时要选用list为存储方式的接口
4.Set是无序的,因为hasSet是无序的
5.当hasSet的一个位置存储重复时,首先在这个位置会使用链表的存储方式,若此位置超过8个存储数据时则会改用二叉树的存储方式。
6.
hasSet在加载75%时就扩容
7.
左移为乘法
右移为除法
8.
链表是按照元素添加的顺序来维护的
9.Q之可以在队头添加或者在队尾删除
10.数据结构的选择:
重复的用List
数据唯一的用Set
队列用Queue
双列存储用Map