ArrayList
import java.util.ArrayList;
import java.util.Iterator;
/*
Collection[接口]:
List[接口]: 元素有序,可以发生重复,有索引的概念
ArrayList[具体的子类]: 底层数据结构是数组,查询快,增删慢,线程不安全,效率高。
Set[接口]: 元素无序且唯一,没有索引
*/
public class ArrayListDemo1 {
public static void main(String[] args) {
//创建集合对象
ArrayList list1 = new ArrayList();
//创建元素对象
//将元素添加到集合中
list1.add("hello");
list1.add("world");
list1.add("java");
list1.add("hadoop");
list1.add("hello");
list1.add("world");
去重及如何比较对象的值
/*
ArrayList
去除集合中字符串的重复值(字符串的内容相同)
*/
//创建一个新的集合
ArrayList list2 = new ArrayList();
//使用contains来判断新数组中是否有重复数据来添加
for (int i = 0; i < list1.size(); i++) {
String str = (String) list1.get(i);
if (!list2.contains(str)) {
list2.add(str);
}
}
import java.util.ArrayList;
/*
去除集合中自定义对象的重复值(对象的成员变量值都相同)
我们按照实现去重字符串的逻辑去重自定义对象,发现自定义对象并没有去重
我们要去看contains的源码,底层判断元素是否存在新集合的逻辑是:
挨个使用待插入的元素与新集合中的元素使用equals方法比较,我们元素Student类中并没有重写equals方法
所以使用的是父类Object中的equals方法,而父类Object中的equals方法比较的是地址值
又因为每一个学生都是new出来的,所以地址值都不一样,比较的结果永远为false
要想比较内容值,需要元素类型重写equals方法,自动生成即可
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name);
}
*/
public class ArrayListTest2 {
public static void main(String[] args) {
ArrayList list1 = new ArrayList();
Student s1 = new Student("李刚", 15);
Student s2 = new Student("钱志强", 16);
Student s3 = new Student("江川", 30);
Student s4 = new Student("李刚", 15);
Student s5 = new Student("祝帅", 15);
list1.add(s1);
list1.add(s2);
list1.add(s3);
list1.add(s4);
list1.add(s5);
System.out.println("list1: " + list1);
System.out.println("=================================");
ArrayList list2 = new ArrayList();
for(int i=0;i<list1.size();i++){
Student s = (Student) list1.get(i);
/*
//Student s1 = new Student("李刚", 15);
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
*/
if(!list2.contains(s)){
list2.add(s);
}
}
System.out.println("list2: " + list2);
}
}
LinkedList
import java.util.LinkedList;
/*
Collection[接口]:
List[接口]: 元素有序,可以发生重复,有索引的概念
ArrayList[具体的子类]: 底层数据结构是数组,查询快,增删慢,线程不安全,效率高。
Vector[具体的子类]: 底层数据结构是数组,查询快,增删慢,先出安全,效率低。
即便Vector是线程安全的,我们以后也不会用它。
特殊的功能:
public void addElement(E obj)
public E elementAt(int index)
public Enumeration elements()
LinkedList[具体的子类]: 底层数据结构是双链表,增删快,查询慢,线程不安全,效率高
特殊功能:
public void addFirst(E e)及addLast(E e)
public E getFirst()及getLast()
public E removeFirst()及public E removeLast()
Set[接口]: 元素无序且唯一,没有索引
*/
public class LinkedListDemo1 {
public static void main(String[] args) {
LinkedList list1 = new LinkedList();
list1.add("hello");
list1.add("world");
list1.add("java");
list1.add("hello");
list1.add("world");
list1.add("hadoop");
System.out.println("list1: "+list1);
System.out.println("=====================");
//public void addFirst(E e)及addLast(E e)
list1.addFirst("李刚");
list1.addLast("钱志强");
System.out.println("list1: "+list1);
System.out.println("----------------------");
//public Object getFirst()及getLast()
System.out.println(list1.getFirst());
System.out.println(list1.getLast());
System.out.println("list1: "+list1);
System.out.println("----------------------");
//public E removeFirst()及public E removeLast()
System.out.println(list1.removeFirst());
System.out.println(list1.removeLast());
System.out.println("list1: "+list1);
}
}
LinkedList面试题
请用LinkedList模拟栈数据结构的集合,并测试
public class MyStack {
private LinkedList linkedList;
MyStack(){
linkedList = new LinkedList();
}
//使用linkedlist.addFirst添加至第一位
public void addYuanSu(Object obj){
linkedList.addFirst(obj);
}
//linkedList.removeFirst()取出第一位
//加上存储的顺序即可做到模拟先进后出的栈数据结构
public Object getYuanSu(){
return linkedList.removeFirst();
}
public int getLength(){
return linkedList.size();
}
@Override
public String toString() {
return "MyStack{" +
"linkedList=" + linkedList +
'}';
}
}
vector
import java.util.Vector;
/*
Collection[接口]:
List[接口]: 元素有序,可以发生重复,有索引的概念
ArrayList[具体的子类]: 底层数据结构是数组,查询快,增删慢,线程不安全,效率高。
Vector[具体的子类]: 底层数据结构是数组,查询快,增删慢,先出安全,效率低。
即便Vector是线程安全的,我们以后也不会用它。
特殊的功能:
public void addElement(E obj)
public E elementAt(int index)
public Enumeration elements()
Set[接口]: 元素无序且唯一,没有索引
*/
public class VectorDemo1 {
public static void main(String[] args) {
//创建Vector集合对象
Vector v1 = new Vector();
//创建元素并添加元素
v1.add("hello");
v1.add("world");
v1.add("java");
v1.add("hadoop");
v1.add("hbase");
v1.add("java");
v1.add("hello");
System.out.println("v1: "+v1);
System.out.println("-------------------------------");
//public void addElement(Object obj) 向集合中添加元素
// v1.addElement("flink");
// System.out.println("v1: "+v1); // 效果和add方法一模一样,可以使用add方法替代
//public Object elementAt(int index) 根据索引获取元素
// System.out.println(v1.elementAt(2));// 效果和get方法一模一样,可以使用get方法替代
// System.out.println(v1.get(2));
//public Enumeration elements()
// Enumeration elements = v1.elements();// 效果和迭代器方法一模一样,可以使用迭代器方法替代
// while (elements.hasMoreElements()){
// System.out.println(elements.nextElement());
// }
}
}
ArrayList,LinkedList,vector的区别
ArrayList、LinkedList 和 Vector 都是 Java 集合框架中的常用列表实现,它们各有优缺点,适用于不同的场景。以下是它们的主要区别:
1. 内部实现
- ArrayList:基于动态数组实现。支持快速的随机访问(通过索引),但在插入和删除元素时(尤其是列表中间位置)效率较低,因为需要移动大量元素。
- LinkedList:基于双向链表实现。插入和删除操作效率高,只需修改节点的引用,但随机访问效率低,因为需要从头或尾遍历链表。
- Vector:与ArrayList类似,也是基于动态数组实现,但它是线程安全的(通过方法同步实现),因此性能通常比ArrayList差。
2. 线程安全性
- ArrayList:非线程安全。在多线程环境下需要手动同步。
- LinkedList:非线程安全。在多线程环境下需要手动同步。
- Vector:线程安全。所有方法都是同步的,但这也带来了额外的性能开销。
3. 性能
- ArrayList:适用于频繁访问元素的场景,因为随机访问速度快(O(1))。插入和删除操作(尤其是中间位置)效率较低(O(n))。
- LinkedList:适用于频繁插入和删除元素的场景,因为这些操作效率高(O(1))。但随机访问效率低(O(n))。
- Vector:由于线程安全的实现,性能通常低于ArrayList。扩容时会将容量翻倍。
4. 扩容机制
- ArrayList:默认初始容量为10,扩容时增加50%。
- Vector:默认初始容量为10,扩容时增加100%(即翻倍)。
- LinkedList:不涉及扩容问题,因为它是基于链表的。
5. 使用场景
- ArrayList:适用于需要频繁访问元素,但插入和删除操作较少的场景。
- LinkedList:适用于需要频繁插入和删除元素的场景,如实现栈、队列等数据结构。
- Vector:适用于需要线程安全的场景,但由于性能问题,现代开发中较少使用。如果需要线程安全的列表,推荐使用
Collections.synchronizedList
或CopyOnWriteArrayList
。
总结
选择合适的列表实现取决于具体的需求和场景:
- 如果需要快速随机访问,选择ArrayList。
- 如果需要频繁插入和删除操作,选择LinkedList。
- 如果需要线程安全且性能要求不高,选择Vector。
泛型
/*
按照之前的写法,有几个问题
1. 程序中有大量的黄色警告
2. 在遍历的时候,迭代器不知道元素本身的类型,需要向下转型
使用泛型[参数化类型]改进集合的使用。
语法格式:<引用数据类型>
*/
/*
泛型是将来用于接收一个引用数据类型的,相当于一个参数
既然是参数,就需要符合标识符的命名规则
一般情况下,使用一个或多个大写字母表示
*/
//泛型类
public class Demo<W> {
public void fun1(W w) {
System.out.println("接收到的参数是:" + w);
}
}
//泛型方法
public <Q> void fun1(Q q) {
System.out.println("接收到的参数是:" + q);
}
//普通的方法
public void fun2(Object obj) {
System.out.println("接收到的参数是:" + obj);
}
}
//泛型接口
public interface Inter1<P> {
void show1(P p);
}
class Inter1Impl<P> implements Inter1<P> {
@Override
public void show1(P p) {
System.out.println("接收到参数值是:" + p);
}
}
/*
泛型通配符
<?>
任意类型,如果没有明确,那么就是Object以及任意的Java类了
? extends E
向下限定,E及其子类
? super E
向上限定,E及其父类
*/
class Demo5{
public void show1(Collection<?> c1){ // 表示可以传入一个Collection集合,元素的类型是任意引用数据类型
System.out.println("任意类型泛型通配符");
}
// 表示可以传入一个Collection集合,元素的类型是Animal或Animal子类的类型
public void show2(Collection<? extends Animal> c1){
System.out.println("? extends Animal类型泛型通配符");
}
// 表示可以传入一个Collection集合,元素的类型是Dog或Dog父类的类型
public void show3(Collection<? super Dog> c1){
System.out.println("任意类型泛型通配符");
}
}
标签:list1,System,add,day13,println,public,out
From: https://www.cnblogs.com/flxf/p/18473216