ArrayList集合
初始数组长度是10, 可以自动扩容
- 产生副本 遍历的是副本
- 遍历副本的时候, 修改的是源集合, 删除副本的元素
- 将副本替换掉原集合
public class Test {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
for (String string : list) {
if(string instanceof String) {
list.remove(string);
}
}
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String obj = it.next();
if(obj instanceof String) {
it.remove();
}
}
// 遍历的就是原集合,不是副本
for (int i = 0; i < list.size(); i++) {
String str = list.get(i);
if(str instanceof String) {
list.remove(str);
// 产生过删除操作的位置,则 i--, 重新检查一遍
i--;
}
}
System.out.println(list);
}
}
List : 有序并且允许重复
LinkedList : 有序并且允许重复
底层数据结构是双向链表 堆栈结构
优点: 插入和删除的时候 效率高
缺点: 遍历和修改的时候 效率低
public class Test2 {
public static void main(String[] args) {
//创建LinkerList集合对象
LinkedList<String> list = new LinkedList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
//头和尾的操作
list.addFirst("z");
list.addLast("y");
System.out.println(list);
String first = list.getFirst();
String last = list.getLast();
System.out.println(first);
System.out.println(last);
list.offerFirst("z");
list.offerLast("y");
System.out.println(list);
String peekFirst = list.peekFirst();
String peekLast = list.peekLast();
System.out.println(peekFirst);
System.out.println(peekLast);
System.out.println(last);
// 获取集合开头和结尾的元素,并且在集合中移除
String pollFirst = list.pollFirst();
String pollLast = list.pollLast();
System.out.println(list);
//弹栈
String pop = list.pop();
System.out.println(pop);
System.out.println(list);
//压栈
list.push("z");
System.out.println(list);
list.add("a");
list.remove("a");
list.removeFirst();
list.removeLast();
//遍历
for (String string : list) {
System.out.println(string);
}
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
iterator.next();
}
Object[] obj = list.toArray();
// 要求向集合中添加10个不重复的10~20之间的随机数
LinkedList<Integer> list2 = new LinkedList<>();
for (int i = 0; i < 10; i++) {
int num = (int)(Math.random()*(20-10+1)+10);
if(!list2.contains(num)) {
list2.add(num);
}else {
i--;
}
}
System.out.println(list2);
}
}
ArrayList 线程不安全的 效率高
Vector 线程安全的 效率低
public class Test3 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(3);
// 可以有顺序的 迭代器 指针默认在 所有元素的前面
ListIterator<Integer> listIterator = list.listIterator();
// 将指针放到 下标为1的元素位置
ListIterator<Integer> listIterator2 = list.listIterator(1);
while (listIterator2.hasPrevious()) {
Integer num = listIterator2.previous();
if(num==3) {
//在遍历过程中添加元素
listIterator2.add(6);
}
}
System.out.println(list);
}
}
hashcode和equals方法
属性值相同则认为是同一个对象 则不添加到集合 , 需要重写hashcode和equals方法
内容相同, 属性 name age 进行计算哈希吗 , 是跟属性相关 跟对象的内存地址无关
默认情况: 根据对象的内存地址,进行一定运算得到的int类型数据
当hashcode方法得到的哈希值 是表中存在的, 则调用equals方法, 让equals进行判断 各个属性是否相同
默认情况是 内存地址不同就存储多分
1.先调用hashcode
2. 如果hashcode不同, 则直接添加到集合
3. 如果hashcode相同. 则调用equals ,
4. equals’结果是true, 不加, equals 结果为false 加
public class Person {
String name;
int age;
String gender;
String hobby;
public Person(String name, int age, String gender, String hobby) {
super();
this.name = name;
this.age = age;
this.gender = gender;
this.hobby = hobby;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
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;
Person other = (Person) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
public class Student {
String name;
int age;
public Student() {
super();
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
// 重写hashcode
@Override
public int hashCode() {
System.out.println("======hashCode===");
// 内容相同, 属性 name age 进行计算哈希吗 , 是跟属性相关 跟对象的内存地址无关
int result = 0;
result+=age;
result+=name.hashCode();
// 默认情况: 根据对象的内存地址,进行一定运算得到的int类型数据
return result;
}
// 当hashcode方法得到的哈希值 是表中存在的, 则调用equals方法, 让equals进行判断 各个属性是否相同
@Override
public boolean equals(Object obj) {
System.out.println("======equals===");
// 重写equals
if(obj instanceof Student){
Student stu = (Student) obj;
if(this.age == stu.age){
if(this.name.equals(stu.name)){
return true;
}
}
}
return false;
}
}
public class Test {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("zzz");
set.add("aaa");
set.add("bbb");
set.add("zzz");
System.out.println(set);
HashSet<Integer> set2 = new HashSet<>();
set2.add(7);
set2.add(8);
set2.add(1);
set2.add(1);
System.out.println(set2);
// 默认情况是 内存地址不同就存储多分
// 需求: 内存地址, 内容相同 都只存储一份
HashSet<Student> set3 = new HashSet<>();
Student stu = new Student("张三",2);
set3.add(stu);
set3.add(new Student("李四",18));
set3.add(new Student("王五",18));
set3.add(new Student("赵六",18));
set3.add(new Student("赵六",18));
System.out.println(set3);
}
public static void add(Student stu) {
// 1. 先调用对象的hashcode方法的到一个哈希值
int hashCode = stu.hashCode();
//2. 去哈希表中查找遍历, 是否有相同的哈希值
//3. 找到相同的了哈希值,但是哈希值相同不一定是相同的对象
//4. 则调用equals方法 进行 判断 每个属性是否相同,
//5. 如果各个属性都相同, 就是相同对象,则不添加
// 如果属性不同,则认为是不同的对象, 就添加
// equals
}
}
public class Test2 {
public static void main(String[] args) {
HashSet<Person> set = new HashSet<>();
set.add(new Person("a", 5, "男", "玩"));
set.add(new Person("a", 5, "男", "玩"));
System.out.println(set);
//集合的嵌套
HashSet<ArrayList<String>> set2 = new HashSet<>();
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("a");
list.add("a");
set2.add(list);
ArrayList<String> list2 = new ArrayList<>();
list2.add("b");
list2.add("b");
list2.add("b");
set2.add(list2);
//遍历集合
for (ArrayList<String> lists : set2) {
for (String string : list2) {
System.out.println(string);
}
}
}
}