集合
数组相当于是存储同一类型的元素的一个容器,但是数组有局限性,数组的长度定义之后就不可以修改,但是在实践中我们经常需要一些可以变长的数据集合.而我们需要对数据的保存的逻辑可能各种各样,于是就有了各种各样的数据结构。Java中对于各种数据结构的实现,就是我们用到的集合。
Java的集合框架是由很多接口,抽象类,具体类组成的.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RVXPlN6w-1606032366575)(C:\Users\LWB\AppData\Roaming\Typora\typora-user-images\1605937398794.png)]
集合与数组相互转化
可以通过循环来转换,也可以直接使用Java定义的方法来转化
public static void main(String[] args) {
//集合转化为数组 先创建一个和集合长度相同的数组,再通过循环将集合中元素的值赋给数组
List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
System.out.println(list);
String [] a=new String[list.size()];
for(int i=0;i<list.size();i++){
a[i]=list.get(i);
}
System.out.println(Arrays.toString(a));
//2.toArray转化
String[] s1 = list.toArray(new String[list.size()]);
System.out.println(Arrays.toString(s1));
//数组转化为集合 1.通过方法直接转换
List<String> list1 = Arrays.asList(a);
System.out.println(list1);
// 2.通过循环来转换
List<String>list2=new ArrayList<String>();
for(int i=0;i<a.length;i++){
list2.add(a[i]);
}
System.out.println(list2);
}
}
Collection
Collection 接口-定义了存取一组对象的方法,其子接口Set和List分别定义了存储方式。
Set 中的数据对象没有顺序且不可以重复。
List 中的数据对象有顺序且可以重复。
在Collection接口中定义了一些共有的方法,
ArrayList
实现了List接口,是长度可变的数组,在内存中是连续的存储空间.
遍历元素和随机访问元素的效率比较高
ArrayList的常用方法
add(int index, E element)
get(int index)
indexOf(Object o) lastIndexOf(Object o)
remove(int index) 删除并返回指定位置元素
removeRange(int fromIndex, int toIndex) 删除指定区间的元素(子类继承使用)
set(int index, E element)
排序:sort(Comparator < ? super E> c)
/*add(int index, E element)
get(int index)
indexOf(Object o) lastIndexOf(Object o)
remove(int index) 删除并返回指定位置元素
removeRange(int fromIndex, int toIndex) 删除指定区间的元素(子类继承使用)
set(int index, E element)
*/
public static void main(String[] args) {
ArrayList list= new ArrayList();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
System.out.println(list);
list.set(2,"t");
System.out.println(list.get(2)); //获取元素
System.out.println(list.indexOf("o")); //如果有就返回下标 如果没有就返回-1
System.out.println(list);
list.sort(new StringComparator()); //排序 sort(Comparator<? super E> c)
System.out.println(list);
}
}
自定义一个比较器Comparator
public class StringComparator implements Comparator<String> {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
}
LinkedList
实现了List接口,LinkedList采用的是链表存储方式,LinkedList的底层是一个双向链表,所以对于数据的修改比ArrayList更加方便快捷。
public static void main(String[] args) {
LinkedList<String> link = new LinkedList<String>();
link.add("1");
link.add("2");
link.add("3");
link.add("4");
link.add("5");
System.out.println("链表的第一个元素是 : " + link.getFirst());
System.out.println("链表的最后一个元素是 : " + link.getLast());
//增强for循环 来获取链表的元素
for(String s:link){
System.out.println(s);
}
}
}
Vector
他也是数组列表,添加了同步锁,线程安全的(还有StringBuffer).
public static void main(String[] args) {
Vector v = new Vector();
v.add("a");
v.add("b");
v.add("c");
v.add("d");
v.add("e");
v.add("f");
v.add("g");
v.removeElement("d");
System.out.println(v);
}
}
List接口结合遍历
1.for循环遍历
ArrayList list= new ArrayList();
list.add("a");
list.add("b");
list.add("c");
list.add("c");
list.add("c");
list.add("f");
list.add("g");
System.out.println(list);
//for循环遍历ii
//注意删除元素后,size发生变化,i增长
/* for (int i = 0; i < list.size(); i++) {
//list.remove(list.get(i));
if(list.get(i).equals("c")){
list.remove(list.get(i));
i--;
}
}
2.增强for循环的遍历
ArrayList list= new ArrayList();
list.add("a");
list.add("b");
list.add("c");
list.add("c");
list.add("c");
list.add("f");
list.add("g");
System.out.println(list);
//增强for循环
//不允许遍历时对元素操作 不然会 ConcurrentModificationException
//操作一次后,必须break
for (Object obj:list) {
list.remove(obj);
break;
}
System.out.println(list);
}
3.迭代器遍历
public class IteratorDemo {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
// 迭代器遍历
// 在迭代器中遍历集合想要删除元素时不能使用集合的remove方法进行删除,而应该使用迭代器本身的remove方法进行操作,这样就不会报错了。
Iterator li = list.iterator();
while(li.hasNext()){
Object obj = li.next();
if(obj.equals("c")){
li.remove();
}
}
System.out.println(list);
}}
泛型
泛型:泛指就是参数化类型,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
1.泛型只能是引用类型
2.泛型的类型参数可以有多个。
3.如果没有定义类型,默认为Object
* 泛型:泛指一种类型,类型不确定,可以以参数的形式传递
* 但必须是引用类型,可以有多个, 默认为Object
* */
public class TypeDemo1<A> {
A a;
public A test(A a1){
return null;
}
public static void main(String[] args) {
TypeDemo1<String> typeDemo1 = new TypeDemo1<>();
typeDemo1.test("a");
}
}
为什么会有泛型:我们使用Object作为类型可以存任意的数据类型,但是在进行一些具体操作如remove时,我们需要向下转型,这时候类型就会出现不匹配的情况,有ConcurrentModificationException异常.
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add("a");
list.add("a");
list.add(false);
list.add(1);
//使用Object作为类型可存任意类型数据,
//具体操作时需向下转型,这时类型会不匹配
for (Object obj : list) {
if (obj instanceof String){
list.remove(obj); //ConcurrentModificationException异常
}
} System.out.println(list);
}}