java基础系列05--集合(1)
JAVA 集合
集合由来:
数组长度是固定,当添加的元素超过了数组的长度时需要对数组重新定义,太麻烦,java内部给我们提供了集合类,能存储任意对象,长度是可以改变的,随着元素的增加而增加,随着元素的减少而减少
数组和集合的区别:
区别1 :
-
数组既可以存储基本数据类型,又可以存储引用数据类型,基本数据类型存储的是值,引用数据类型存储的是地址值
-
集合只能存储引用数据类型(对象)集合中也可以存储基本数据类型,但是在存储的时候会自动装箱变成对象
区别2:
- 数组长度是固定的,不能自动增长
- 集合的长度的是可变的,可以根据元素的增加而增长
Collection集合
集合.png* boolean add(E e)
* boolean remove(Object o)
* void clear()
* boolean contains(Object o)
* boolean isEmpty()
* int size()
public static void main(String[] args){
Collection c1 = new ArrayList(); // Collection是接口,父类引用指向子类对象
boolean b1 = c1.add("abc"); // true
boolean b2 = c1.add(new Person()); // true
c1.add(true); // true 添加任何都能返回true
System.out.println(c1); //ArrayList 父类重写了toString方法 [abc, com.test.Person@15db9742, true]
System.out.println(c1.remove("abc")); //true 删除成功返回true,否则为false
System.out.println(c1.contains("a"));// false
System.out.println(c1.size()); //2 集合中元素个数
}
集合转数组并且进行遍历(了解):
public class Student {
public static void main(String[] args){
Collection c = new ArrayList();
c.add("a");
c.add("b");
c.add("c");
c.add("d");
Object[] arr = c.toArray();
for(int i=0;i<arr.length;i++){
System.out.println(arr[i]); // a b c d
}
c.clear();
c.add(new Person("张三",12));
c.add(new Person("李四",13));
c.add(new Person("王五",14));
c.add(new Person("赵六",15));
Object[] arr1 = c.toArray();
for(int i =0;i<arr1.length;i++){
// System.out.println(arr1[i].getName()); //此时arri[i] 的类型提升到了Object,要调用对象特有的方法需要向下转型
Person p = (Person)arr1[i]; // 需要向下转型
System.out.println(p.getName()+"----"+p.getAge()); // 张三----12 李四----13 王五----14 赵六----15
}
}
}
Collection集合的带All的方法:
boolean addAll(Collection c) // c1.addAll(c) 将集合c中的每个元素添加到C1
boolean removeAll(Collection c) // c1.removeAll(c) 删除c1中含有的c元素,删除交集
boolean containsAll(Collection c) //c1.containsAll(c) c1是否包含c,和顺序有关
boolean retainAll(Collection c) // c1.retainAll(c) c1保留和c的交集,其余删除,调用的集合改变则返回true,不变则返回false
集合的遍历之迭代器遍历:
Collection c = new ArrayList();
c.add("a");
c.add("b");
c.add("c");
c.add("d");
Iterator it = c.iterator(); //获取迭代器
while(it.hasNext()){ // 若有元素,则返回true,没有返回false
System.out.println(it.next()); // a b c d
}
List 集合特有功能
* boolean add(E element) // 添加元素
* void add(int index,E element)//根据索引添加元素
* E remove(int index) //根据索引移除元素
* E get(int index) //根据索引获取元素,可以遍历List集合
* E set(int index,E element) // 修改指定位置的元素
并发修改异常的解决方法 (ListIterator):
public static void main(String[] args){
List c = new ArrayList();
c.add("a");
c.add("b");
c.add("c");
c.add("d");
// Iterator its = c.iterator(); //获取迭代器
// while(its.hasNext()){
// if( its.next() == "c"){
// c.add("xx"); //报错 java.util.ConcurrentModificationException
// }
// }
ListIterator it = c.listIterator(); // 获取迭代器(list集合特有的)
while(it.hasNext()){
if(it.next() == "c"){
it.add("xx");
}
}
System.out.println(c); // [a, b, c, xx, d]
}
List的三个子类的特点:
ArrayList:
底层数据结构是数组,查询快,增删慢。
线程不安全,效率高。
Vector:
底层数据结构是数组,查询快,增删慢。
线程安全,效率低。
Vector相对ArrayList查询慢(线程安全的)
Vector相对LinkedList增删慢(数组结构)
LinkedList:
底层数据结构是链表,查询慢,增删快。
线程不安全,效率高。
查询多用ArrayList
增删多用LinkedList
Vector集合(被替代掉了,面试用)
vector是线程(Thread)同步(Synchronized)的,所以它也是线程安全的,而Arraylist是线程异步(ASynchronized)的,是不安全的。如果不考虑到线程的安全因素,一般用Arraylist效率比较高。
Vector v = new Vector();
v.addElement("a");
v.add("b");
ListIterator its = v.listIterator();
while(its.hasNext()){
System.out.println(its.next());
}
System.out.println(v);
ArrayList
public static void main(String[] args){
// 去除ArraryList的重复项
ArrayList a = new ArrayList();
a.add("a");
a.add("b");
a.add("b");
a = getSingleList(a);
System.out.println(a); //[a, b]
}
public static ArrayList getSingleList(ArrayList arr){
Iterator i = arr.iterator();
ArrayList a = new ArrayList();
while(i.hasNext()){
Object temp = i.next();
if (!a.contains(temp)){ // 若集合中保存的是自定义对象则自定义对象需要重写equals方法
a.add(temp);
}
}
return a;
}
LinkedList的特有功能:
public static void main(String[] args){
LinkedList l = new LinkedList();
l.addFirst("a"); // a
l.addFirst("b"); // b a
l.addLast("c"); // bac
l.add("d"); //bacd
Object first = l.getFirst(); // b
Object last = l.getLast(); // d
l.removeFirst(); //delete the "b"
l.removeLast(); // delete the "d"
Object s = l.get(1); // 根据索引获取对应的元素,
System.out.println(l); // [a,c]
System.out.println(s); // c
}
泛型:
限定某个集合的存储元素类型,提高安全性(将运行期的错误转换到编译期) ,省去强转的麻烦
规定:<>中放的必须是引用数据类型, 前后的泛型必须一致,或者后面的泛型可以省略不写(1.7的新特性菱形泛型)
//ArrayList<Person> arr1 = new ArrayList<>(); 后面的泛型可以省略不写(1.7的新特性菱形泛型)
//ArrayList<int> arr2 = new ArrayList<Person>(); 错误,泛型限定一定要是引用数据类型,可以写Integer
//ArrayList<Object> arr3 = new ArrayList<Person>(); 报错,前后泛型不一致,而且泛型定义成Object无意义
ArrayList<Person> arr = new ArrayList<Person>();
arr.add(new Person("张三",11));
arr.add(new Person("李四",13));
Iterator<Person> i = arr.iterator(); // 使用泛型限定元素类型
while (i.hasNext()){
Person p = i.next();
System.out.println(p.getAge()+"----"+p.getName());
}
给自己的类加泛型
class Tool<E>{
private E e;
public E getObj(){
return e;
}
public void setObj(E e){
this.e = e;
}
public<T>void show(T t){ // 方法泛型需要与类的一直,如果不一致,则需要在方法上声明泛型
System.out.println(t);
}
public static<W> void shows(W e){ // E是在创建对象的时候才赋值,但是静态则是不用创建对象就能直接调用的
// 所以静态方法必须要给出自己的泛型
System.out.println(W); // 可以写E,这里写E的话和类的E就是不同的变量,只是名字相同
}
}
泛型接口:
interface Inter<T>{
public void show (T t);
}
class Demo implements Inter<String>{
@Override
public void show(String t) {
System.out.println(t);
}
}
泛型高级之通配符(了解):
List<?> list = new ArrayList<String>();
增强for 循环遍历数组和集合
增强for 循环底层依赖的是迭代器
public static void main(String[] args){
// 增强 for循环遍历数组
int[] arr = new int[]{11,22,33,44};
for (int i : arr) {
System.out.println(i); //11 22 33 44
}
// 增强 for循环遍历集合
ArrayList<String> list = new ArrayList<>();
list.add("aa");
list.add("bb");
list.add("cc");
list.add("dd");
for (String string : list) {
System.out.println(string); // aa bb cc dd
}
}
三种在遍历的时候删除集合元素:
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("b");
list.add("c");
// -------第一种删除方式-------------
// for (int i = 0; i < list.size(); i++) {
// if ("b".equals(list.get(i))){
// list.remove(i);
// i--; // 需要加这句,才能删除2个b,不加只能删除一个
// }
// }
// -------第二种删除方法-------------
Iterator<String> it = list.iterator();
while(it.hasNext()){
if ("b".equals(it.next())){
it.remove(); // 不能使用集合的删除,只能使用迭代器的删除,否则并发修改异常
}
}
// -------第三中删除方法( 不行并发修改异常)--------
// for (String string : list) {
// if ("b".equals(string)){
// list.remove("b");
// }
// }
JDK1.5的可变参数:
如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个
public static void main(String[] args){
int[] arr = new int[]{1,2,3,4};
print(arr); // 结果都一样
print(1,2,3,4);
}
public static void print(int... arr){
// 可变参数,这里的 arr就是一个数组
for (int i : arr) {
System.out.println(i);
}
}
Arrays工具类的asList()方法的使用
public static void main(String[] args){
Integer[] arr = {11,22,33,44};
// 将数组看作集合去使用,但是不能使用集合的增加和删除方法,其他的方法可以使用
List<Integer> list = Arrays.asList(arr);
//list.add(55); // 编译不报错,但是增加和删除会报错,不能操作
//list.remove(1);// 编译不报错,但是增加和删除会报错,不能操作其余方法可以
System.out.println(list.get(1)); // 22
}
// 集合转为数组
public static void main(String[] args){
ArrayList<String> arr = new ArrayList<String>();
arr.add("a");
arr.add("b");
arr.add("c");
String[] arrs = arr.toArray(new String[0]);
for (String string : arr) {
System.out.println(string);
}
}