List接口的链接列表实现
public void addFirst(E e)将指定元素插入此列表的开头
public void addLast(E e)将指定元素添加到此列表的结尾
public E removeFirst()移除并返回此列表的第一个元素
public E removeLast()移除并返回此列表的最后一个元素
public E getFirst()获取本列表的第一个元素
public E getLast()获取本列表的最后一个元素
LinkedList也可以存储字符串和自定义对象
使用ArrayList去除掉集合中字符串中的重复值
1️⃣新建一个集合list2,遍历list,如果list2中没有正在遍历的值,就将他插入list2,最后用迭代器对list2进行遍历
private static void removeAgain(ArrayList list) {
ArrayList list2 = new ArrayList();
for(int i=0;i<list.size();i++){
Object object = list.get(i);
if(!list2.contains(object)){
list2.add(object);
}
}
Iterator iterator = list2.iterator();
while(iterator.hasNext()){
Object next = iterator.next();
System.out.println(next);
}
}
2️⃣遍历这个数组,拿前面的数值和后面的数值作比较,一旦发现值相等,就将后面的删除,删除之后索引变量需要-1(ArrayList基于数组,索引发生改变)
private static void removeAgain2(ArrayList list) {
// TODO Auto-generated method stub
for(int i=0;i<list.size();i++){
for(int j=i+1;j<list.size();j++){
if(list.get(i).equals(list.get(j))){
list.remove(j);
j--;
}
}
}
Iterator iterator = list.iterator();
while(iterator.hasNext()){
Object next = iterator.next();
System.out.println(next);
}
}
使用LinkedList去重自定义对象
新建一个List2,遍历list,如果list2没有contains这个元素,就将它插入到list2中。
private static void removeAgain(LinkedList list) {
// TODO Auto-generated method stub
LinkedList list2 = new LinkedList();
for(int i=0;i<list.size();i++){
Object object = list.get(i);
if(list2.contains(object)){
list2.add(object);
}
}
showList(list2);
}
泛型:为了避免类型强转发生错误,泛型左边和右边类型一致,新特性右边可以根据左边推测类型
泛型的好处:
1.提高了安全性
2.省去了类型强转可能发生的错误
3.将运行时期的错误提前到了编译时期
泛型只存在于编译时期,编译之后就不存在了。
在类上面自定义泛型:
public class Demo5 {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyArrayList<String> list = new MyArrayList<>();
list.add("姚作鹏最帅");
String string = list.get(0);
System.out.println(string);
}
}
// 泛型定义在类上面,如果创建类的时候不指定确定的类型,那么默认的就是Object类型,如果指明了明确的类型,那么这个泛型在整个类就是这个指定的类型
class MyArrayList<T> {
Object[] arr = new Object[10];
public boolean add(T e) {
// 遍历数组看哪个元素是空,是的话就添加值
for (int i = 0; i < arr.length; i++) {
Object value = arr[i];
break;
}
return true;
}
public T get(int index) {
return (T) arr[index];
}
@Override
public String toString() {
String result = "[";
for (int i = 0; i < arr.length; i++) {
Object value = arr[i];
if (value != null) {
result += value + " ";
}
}
result = result.trim();
result += "]";
return result;
}
}
在方法上面自定义泛型:
public static void main(String[] args) {
// TODO Auto-generated method stub
Object obj="哈哈";
String s=change(obj);
String s2=(String) obj;
Object obj2=123;
Integer i=change(obj2);
Integer i2=(Integer) obj2;
}
// 用于类型强转的泛型方法
public static<T> T change(Object obj){
return (T) obj;
}
自定义泛型在类和方法上的区别:
自定义泛型在方法上是为了类型的强转,作用域是整个方法,
自定义泛型在类上作用域是在整个类内部。
带泛型的接口的子类:
如果不指定接口的泛型,那么子类也需要泛型下去,而且名字要一模一样都为<T>或者<E>
指定父接口的泛型,此时可以定义自己的泛型,也可以不定义自己的泛型
接口代码
public interface GenerInter<T> {
T show();
}
实现接口代码
public class GenerDemo<T> implements GenerInter<T> {
@Override
public T show() {
// TODO Auto-generated method stub
return null;
}
}
泛型通配符
? 代表任何类型,包括Object类型
?extend E 代表E本身或者E的子类 向下限定通配符
?super E 代表E本身或者E的父类向上限定通配符
ArrayList<Animal> list = new ArrayList<Dog>();
ArrayList<?> list2 =new ArrayList<Dog>();
ArrayList<? extends Animal> list3 =new ArrayList<Dog>();
ArrayList<?super Dog> list4 =new ArrayList<Animal>();
Animal是Dog的父类,也无法直接添加泛型,。只能使用通配泛型
使用向下限定通配符,因为不确定是哪个子类,所以无法添加值,但是可以取值
ArrayList<? extends Animal> list3 =new ArrayList<Dog>();
ArrayList<? extends Animal> list4 =new ArrayList<Cat>();
ArrayList<? extends Animal> list5 =new ArrayList<Dog>();
public static void test(Collection<? extends Animal> list){
Iterator<? extends Animal> iterator = list.iterator();
Animal next = iterator.next();
}
向上限定通配符既可以添加值,也可以取值
增强for循环Foreach
for (要遍历的数据类型 要遍历的变量名字 : 要遍历的数组或者集合) {
对遍历的值进行操作的语句
}
ArrayList<String> list = new ArrayList<>();
list.add("1.夏红");
list.add("2.阿翔");
list.add("3.炸天");
list.add("4.腰子");
System.out.println(list);
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i) + " ");
}
System.out.println();
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
System.out.println();
for (String string : list) {
System.out.print(string);
}
System.out.println();
}
四种遍历方式。其中Foreach内部运行是迭代器。。
迭代器在进行迭代元素的时候不能够直接使用集合修改元素
数组一般为int value:arr 输出value
集合一般为String string:list 输出string
可变参数:当不知道方法的参数定义几个的时候,使用可变的参数
修饰符 返回值 方法名(数据类型...变量名){
方法体;
}
可变参数本质上是一个数组。
如果参数列表有多个参数时且存在可变参数时,无论数据类型。可变参数永远放在最后面。
public static void main(String[] args) {
test(1,2,3,4,5,"李白");
}
private static void test(int...arr,String a) {
// TODO Auto-generated method stub
}
这样是错误的。
public static<T> List<T>asList(T...a)将一个数组转化为集合
Integer[] arr={1,2,3,4};
List<Integer> asList = Arrays.asList(arr);
集合只能存储引用类型数据,只能存储基本数据类型的包装类。
Object[] toArray() 返回按适当顺序包含列表元素的数组从第一个到最后一个
Object[] array = asList.toArray();
Set集合:内部不能有重复的值
HashSet:存入的顺序和取出的顺序并不能保持一致。所以需要Linked
HashSet:是哈希表结构,内部依靠元素对象的hashCode和equals方法去重的,首先会判断两个对象hash值是否相同,相同再调用equals进行判断。
所以需要重写Person类中的hashCode方法和equals方法
LinkedHashSet:使用链表和哈希表
它是用链表保证元素的存入顺序和取出顺序一致。由哈希表保证元素的唯一性。
HashSet和LinkedHashSet的区别就是有序和无序
使用LinkedHashSet写一个取10个0-20随机数的小程序
public static void main(String[] args) {
LinkedHashSet<Integer> set = new LinkedHashSet<Integer>();
Random r = new Random();
while (set.size() < 10) {
int number = r.nextInt(20) + 1;
set.add(number);
}
Iterator<Integer> iterator = set.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
}
Map<K,V>。以键值对的方式存储:将键映射到值得对象,一个映射不能包含重复的键,每个键最多只能映射到一个值。
Map集合和Collection集合异同:
Map集合是双列的,Collection集合是单列的
Map集合存储的是以键值对的方式:key=value
Map可以有重复的值,不能存在重复的键
Map集合通过哈希表的结构保证键的唯一
Map集合是接口,里面的方法不能直接使用,所以使用它的子类HashMap,基于哈希表的Map接口实现,允许使用null值和null键(除了非同步和允许使用null外,HashMap和HashTable大致相同),此类不保证映射的顺序
map.put(110, "警电话");
map.put(120, "急救电话");
map.put(119, "火警电话");
map.put(1123, "警电话");
{1123=警电话, 119=火警电话, 120=急救电话, 110=警电话}
可以多个键指定同一个值。
map.put(110, "警电话");
map.put(120, "急救电话");
map.put(119, "火警电话");
map.put(119, "警电话");
{119=警电话, 120=急救电话, 110=警电话}
同一个键指向多个值,会被覆盖
HashMap方法
v put(K key,V value) 将指定的值和此映射中的指定键关联,返回的是以前和key关联的值
v remove(Object key) 移除此键对应的值,返回的是移除的值
void clear() 清空map集合
boolean containsKey(Object Key) 判断是否包含指定的键
boolean containsValue(Object Value) 判断是否包含指定的值
boolean isEmpty() 判断集合是否为空
int size() 返回Map集合中键值对的个数
Map集合的两种遍历方式
V get<Object key> 指定键所映射的值,如果此键不包含映射关系,返回null
Set<K> keySet() 获取键集
Collection<V> values() 获取值集
Set<Map.Entry<K,V> entrySet()> 获取键值对映射关系集
第一种遍历集合方式
获取所有的键,然后遍历所有的键,通过键取值
HashMap<Integer, String> map = new HashMap<Integer, String>();
map.put(110, "警电话");
map.put(120, "急救电话");
map.put(119, "火警电话");
Collection<Integer> keys = map.keySet();
for (Integer key : keys) {
String value = map.get(key);
System.out.println(key+"="+value);
}
第二种遍历方式
获取键值对对象集合,然后遍历键值对集合,通过键值对对象获取键和值
for (Map.Entry<Integer, String> entry : map.entrySet()) {
System.out.println(entry.getKey()+"="+entry.getValue());
}
HashMap类存储几种不同类型键和值案例
HashMap<String,String>
HashMap<String,Person>
HashMap<Person,String>
HashMap<String, Person> map = new HashMap<>();
map.put("number 1", new Person("张三", 18, '男'));
map.put("number 2", new Person("张四", 18, '男'));
map.put("number 3", new Person("张五", 18, '男'));
map.put("number 4", new Person("张六", 18, '男'));
for (Map.Entry<String, Person> entry : map.entrySet()) {
System.out.println(entry.getKey() + "=" + entry.getValue());
}
Map集合嵌套List集合
public static void main(String[] args) {
// TODO Auto-generated method stub
HashMap<String, ArrayList<String>> map = new HashMap<String, ArrayList<String>>();
ArrayList<String> list = new ArrayList<>();
list.add("吕布");
list.add("赵云");
map.put("三国演义", list);
ArrayList<String> list2 = new ArrayList<>();
list2.add("孙悟空");
list2.add("猪八戒");
map.put("西游记", list2);
ArrayList<String> list3 = new ArrayList<>();
list3.add("令狐冲");
list3.add("林平之");
map.put("笑傲江湖", list3);
for (Map.Entry<String, ArrayList<String>> entry : map.entrySet()) {
String key = entry.getKey();
System.out.println(key);
ArrayList<String> value = entry.getValue();
// 遍历ArrayList集合
for (String data : value) {
System.out.println("\t"+data);
}
}
}
实现思路:先遍历出所有list,在list里面遍历元素
Map嵌套Map,实现层层加密,三层联动等
三层密码map(map(map))
private static void test() {
// 1.创建这个锦囊
HashMap<Integer, String> map = new HashMap<Integer, String>();
map.put(110, "让孙夫人摆平东吴的追兵,她是孙权妹妹,东吴将领惧她三分");
// 2.创建第二层防护
HashMap<Integer, HashMap<Integer, String>> map2 = new HashMap<Integer, HashMap<Integer, String>>();
map2.put(120, map);
// 3.创建第三层防护
HashMap<Integer, HashMap<Integer, HashMap<Integer, String>>> map3 = new HashMap<Integer, HashMap<Integer, HashMap<Integer, String>>>();
map3.put(119, map2);
// 4.拆解锦囊
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请输入最外层的密码:");
int pwd = sc.nextInt();
HashMap<Integer, HashMap<Integer, String>> map4 = map3.get(pwd);
if (null != map4) {// 说明密码正确,获取成功
//解开第二层的防护
while(true){
System.out.println("请输入第二层的密码:");
int pwd2 = sc.nextInt();
HashMap<Integer,String> map5 = map4.get(pwd2);
if(map5!=null){
//拆开最后一层防护
while(true){
System.out.println("请输入最后一层的密码:");
int pwd3 = sc.nextInt();
String result = map5.get(pwd3);
if(null!=result){
System.out.println(result);
//如果代码进入了这里,说明锦囊以及被打开了,直接结束while循环
break;
}
//如果代码走到这里,说明最后一层防护没有被解开
System.out.println("最后一层密码输出错误,请重新输出");
}
//如果代码进入了这里,说明第二层防护解开了,那么就结束这个while循环
break;
}
System.out.println("第二层密码输出错误,请重新输出");
}
//进来了就说明密码是正确的,就可以结束这个while循环
break;
}
System.out.println("最外层密码输出错误,请重新输出");
}
}
三级联动map(map(list))
private static void test2() {
/*
* ["东城区", "西城区", "崇文区", "宣武区", "朝阳区", "丰台区", "石景山区", "海淀区", "门头沟区", "房山区", "通州区", "顺义区", "昌平区", "大兴区", "怀柔区", "平谷区", "密云县", "延庆县", "延庆镇"]);
dsy.add("0_0", ["北京市"]);
*/
HashMap<String, ArrayList<String>> map = new HashMap<String,ArrayList<String>>();
ArrayList<String> list = new ArrayList<String>();
list.add("东城区");
list.add("西城区");
//。。。
map.put("北京市", list);
// map.put("北京市", "西城区");
// map.put("北京市", "崇文区");
// map.put("北京市", "宣武区");
// map.put("北京市", "丰台区");
// map.put("北京市", "石景山区");
HashMap<String, ArrayList<String>> map2 = new HashMap<String,ArrayList<String>>();
ArrayList<String> list2 = new ArrayList<String>();
list2.add("瑶海区");
list2.add("包河区");
map2.put("合肥市", list2);
ArrayList<String> list3 = new ArrayList<String>();
list2.add("金安区");
list2.add("叶集区");
map2.put("六安市", list3);
HashMap<String, HashMap<String, ArrayList<String>>> map3 = new HashMap<String,HashMap<String, ArrayList<String>>>();
map3.put("北京省", map);
map3.put("安徽省", map2);
}
List嵌套Map
private static void test() {
ArrayList<LinkedHashMap<String, String>> list = new ArrayList<LinkedHashMap<String, String>>();
LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
map.put("周瑜", "小乔");
map.put("吕布", "貂蝉");
list.add(map);
LinkedHashMap<String, String> map2 = new LinkedHashMap<String, String>();
map2.put("郭靖", "黄蓉");
map2.put("杨过", "小龙女");
list.add(map2);
LinkedHashMap<String, String> map3 = new LinkedHashMap<String, String>();
map3.put("令狐冲", "任盈盈");
map3.put("林平之", "岳灵珊");
list.add(map3);
// 遍历
for (LinkedHashMap<String, String> map4 : list) {
// 遍历map4
for (Map.Entry<String, String> entry : map4.entrySet()) {
System.out.println(entry.getKey() + "---" + entry.getValue());
}
System.out.println();// 输出一个Map集合后,需要换一行
}
}
Collections类概述和成员方法:等同于Arrays,是对集合进行操作的工具类
成员方法:
public static <T> void sort(List<T> list) 对元素进行升序排序
public static <T> int binarySearch(List<?>list,T key)查找指定key在指定list集合中的位置索引,list集合必须是有序的
public static <T> T max(Collection<?> coll) 获取一个集合中最大的值
public static void reverse(List<?> list) 将集合中的元素反转。本身升序,反转就成了降序。二分法只有在升序的情况下才可以用
public static void shuffle(List<?> list) 将集合中的元素随即打乱(模仿斗地主发牌)
斗地主发牌系统(Collections类成员方法的实战)
public static void main(String[] args) {
// 1.创建存放牌的容器,小王14,大王15
// 2.将所有的牌都放在容器里面
ArrayList<Integer> list = new ArrayList<Integer>();
for (int i = 1; i <= 4; i++) {
for (int j = 1; j <= 13; j++) {
list.add(j);
}
}
list.add(14);
list.add(15);
// 3.打乱容器里的牌
Collections.shuffle(list);
// 4.将牌分配给四个人%4=(0-3)
ArrayList<Integer> list2 = new ArrayList<>();
ArrayList<Integer> list3 = new ArrayList<>();
ArrayList<Integer> list4 = new ArrayList<>();
ArrayList<Integer> list5 = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
switch (i % 4) {
case 0:
list2.add(list.get(i));
break;
case 1:
list3.add(list.get(i));
break;
case 2:
list4.add(list.get(i));
break;
case 3:
list5.add(list.get(i));
break;
}
}
// 5.将每个人获取的牌都排好序
Collections.sort(list2);
Collections.sort(list3);
Collections.sort(list4);
Collections.sort(list5);
// 6.将每个人的牌展示出来,展示的时候不能全是数字,要有JKL,小王,大王。
show(list2);
System.out.println();
show(list3);
System.out.println();
show(list4);
System.out.println();
show(list5);
}
private static void show(ArrayList<Integer> list) {
for (int i = 0; i < list.size(); i++) {
Integer value = list.get(i);
switch (value) {
case 11:
System.out.print("J ");
break;
case 12:
System.out.print("K ");
break;
case 13:
System.out.print("Q ");
break;
case 14:
System.out.print("小王 ");
break;
case 15:
System.out.print("大王 ");
break;
default:
System.out.print(value + " ");
break;
}
}
}
public static <T> void sort(List<T> list,Comparator<? super T> c)根据指定比较器产生的顺序对指定列表进行排序
比较器接口一般是用于给java提供好的类进行排序的
对String和Integer进行排序
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("yz");
list.add("gh");
list.add("ef");
list.add("cd");
list.add("ab");
System.out.println(list);
Collections.shuffle(list);
System.out.println(list);
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
// TODO Auto-generated method stub
//o1和o2比较是升序
//o2和o1比较是降序
return o1.compareTo(o2);
}
});
System.out.println(list);
}
Integer同理
Comparator进行二分法
因为排序和查找要使用同一个Comparator,所以将后部分分离出来。
public static void main(String[] args) {
Comparator<String> c=new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
// TODO Auto-generated method stub
//o1和o2比较是升序
//o2和o1比较是降序
return o1.compareTo(o2);
}
};
ArrayList<String> list = new ArrayList<String>();
list.add("yz");
list.add("gh");
list.add("ef");
list.add("cd");
list.add("ab");
System.out.println(list);
Collections.shuffle(list);
System.out.println(list);
Collections.sort(list, c);
System.out.println(list);
System.out.println(Collections.binarySearch(list, "yz"));
}
定义了一个Comparator,无论是sort排序还是二分法查找,都可以直接调用
自定义元素对象的升序和降序
private static void test2() {
ArrayList<Person> list = new ArrayList<Person>();
list.add(new Person("wangwu",18));
list.add(new Person("lisi",18));
list.add(new Person("wangwu",28));
list.add(new Person("zhaoliu",38));
list.add(new Person("dahuang",8));
//列表中的所有元素都必须实现 Comparable 接口
Collections.sort(list);
showList(list);
}
private static void showList(ArrayList<Person> list) {
for(Person p : list){
System.out.println(p);
}
}
如果使用Arrays和Collections的sort方法对象元素进行排序,这个列表元素必须实现Comparble类
public class Person implements Comparable<Person>{
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
@Override
public int compareTo(Person o) {
//this和o比较是升序
//首先比较年龄是否相等,相等就比较姓名,如果不相等就直接比较年龄
//return this.age==o.age?this.name.compareTo(o.name):this.age-o.age;
//o和this比较是降序
//首先比较姓名是否相等,相等就比较年龄,如果不相等就直接比较姓名
return o.name.equals(this.name)?o.age-this.age:o.name.compareTo(this.name);
}
}
比较器Comparator和Comparable接口同时存在时,以比较器为主。