Java基础学习
迭代器
1、迭代器的指针一开始在集合的上方
next()
:指针下移,下移以后返回指针指向的值
2、使用迭代器遍历集合元素
//正确写法
Iterator iterator=coll.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
//错误写法,每次都新创建一个迭代器对象,输出的结果一直为集合中第一个元素
//迭代器并不是单例模式,返回的必须是同一个对象才可以
// Iterator iterator1=coll.iterator();
while (coll.iterator().hasNext()){
System.out.println(coll.iterator().next());
}
3、使用增强for
循环遍历元素
//对于集合来说,增强for循环底层调的还是迭代器,return new iter()实现类的对象
for (Object obj:coll){
System.out.println(obj);
}
4、两种for
循环赋值操作的不同
字符串不能对内容进行修改,但字符串数组可以修改元素值。
使用方法2当修改对象的属性时,属性不会进行更改。
//赋值操作1
for (int i = 0; i < str.length; i++) {
str[i]="DD";
}
//赋值操作2 不能改变原字符数组的值,只是改变了局部变量s的值
for (String s:str){
s="FF";
}
List
1、除了继承Collection接口的抽象方法外,根据List的有序性(具有索引)新增方法:
- 删:remove(int index)
- 改:set(int index,Object o)
- 查:get(int index) 得到List的对应索引的值,并不是list[i]而是用list.get(index)
- 插:add(int index,Object o) 和增的不同在于指定索引
- addAll(int index,Collection c)
2、ArrayList
对象可以通过对象名直接进行输出,遍历一个一个输出可以用上述两种方法
List list = new ArrayList();
System.out.println(list);//相当于list.tostring()
此时输出list
中的所有元素内容,因为是AbstractCollection
的实现类,其底层为:
public String toString() {
Iterator<E> it = iterator();
if (! it.hasNext())
return "[]";
StringBuilder sb = new StringBuilder();
sb.append('[');
for (;;) {
E e = it.next();
sb.append(e == this ? "(this Collection)" : e);
if (! it.hasNext())
return sb.append(']').toString();
sb.append(',').append(' ');
}
}
使用了迭代器,StringBuilder
3、List
接口的三大实现类
因为有序,ArrayList插入和删除数据时,如果不是最后一个所有修改位置的后面数据都要进行移位,因此效率低。
4、Arraylist.remove()
方法里面为数字时默认为索引,若要删除内容需要将数字封装成Integer
对象,当数字内容为128时,也同样可以删除,因为底层是equals
,比较的是内容。
Set
1、Set
的常用方法为Collection
中声明的15个抽象方法,没有新增的方法,List
有是因为有序,可以根据序号增加、删除和查找元素
2、Set中无序性、不可重复性的理解,不包括TreeSet
无序:并不是说添加元素的顺序和遍历元素的顺序不一致就是无序性,而是指在数组中的存储位置,不是依次排列的,此行为表现为无序性。
equals()
和hashCode()
保持一致性是指,当equals相等时hashCode()一定相等,但hashCode()相等时equals()不一定相等。
3、TreeSet
底层原理和HashSet
以及LinkedHashSet
不同,当指定元素的属性大小相同时,则判断为重复,不会再出现在集合中;
TreeSet中的元素必须是同一个类型对象,否则会报ClassCastException
,由后面的.compare(前面已添加的对象)
;
使用contains
和remove
方法时,不再是使用hashCode()
和equals()
方法了,比较元素大小或元素是否相等看compareTo()
或compare()
的返回值,其中compareTo()是引用数据类互相进行比较的方法,compare()是基本数据互相进行比较的方法。
Map
1、并不是Collection接口的子接口,两者是独立的管理,因此方法也独立:
- 增:put(Object key,Object value)
- putAll(Map m)
- 删:remove(Object key) 返回删除的键值对中value的值
- 改:put(Object key,Object value) 返回原键值对中value的值
- putAll(Map m) 没有返回值
- 长度:size()
遍历:
遍历key值 map.keySet() 返回Set实例
遍历value集:map.value() 返回Collection实例
遍历entry集:map.entrySet() 返回Set实例
2、LinkedHashMap
是LinkedHashSet
的底层。
3、面试:HashMap和Hashtable的区别,HashMap和LinkedHashMap的区别
Hashtable不可以添加null的key或value值
4、Map中Key
是Set
,不能重复且是无序排列,而Value
是可以重复无序排列算是Collection
(一个一个的数据)。
Key和Value看成一个整体为一个Entry
(某一个类)的两个属性,不能重复且无序
5、Set
遍历有两种方式,分别是迭代器和增强for循环;
List
遍历有三种方式,上诉两种再加一个for循环。
6、当TreeMap
中key
的compareTo
返回0时,后面重复的key不会再进入key集合中,而添加重复key的value时,原相同key的value值会被修改。
TreeMap不是使用hashCode()和equals()判断大小和是否相等,而是使用compareTo()
Collections工具类(均为static方法)
1、Collection:集合框架中的一个用于存储一个一个元素的接口,又分为List和Set等子接口。
Collections:用于操作集合框架的一个工具类,包括Set、List、Map。
常用方法:
排序操作:
- reverse(List):反转 List 中元素的顺序
- shuffle(List):对 List 集合元素进行随机排序
- sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
- sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
- swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换
查找:
- Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
- Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素
- Object min(Collection):根据元素的自然顺序,返回给定集合中的最小元素
- Object min(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最小元素
- int binarySearch(List list,T key)在List集合中查找某个元素的下标,但是List的元素必须是T或T的子类对象,而且必须是可比较大小的,即支持自然排序的。而且集合也事先必须是有序的,否则结果不确定。
复制、替换:
- void copy(List dest,List src):将src中的内容复制到dest中
- boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值
- 提供了多个unmodifiableXxx()方法,该方法返回指定 Xxx的不可修改的视图。
添加:
- boolean addAll(Collection c,T... elements)将所有指定元素添加到指定 collection 中。
同步
- Collections 类中提供了多个 synchronizedXxx() 方法,该方法可使将指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题:
例如:synchronizedCollection()、synchronizedList()、synchronizedMap()
2、使用Collections.sort(),括号中集合的元素必须是同一类型,否则无法比较大小。
3、使用max()和min()方法,返回的是排序之后最右边和最左边的值。
如果是自然排序则是最大值和最小值,如果方法中传入定制比较方法,则按定制比较方法的顺序来取得最大值和最小值。
4、使用Collections.copy()方法时,dest.size()>=src.size();
//错误行为,因为此时dest的size=0,不符合copy的要求
// List dest=new ArrayList();
// Collections.copy(dest,src);
//使用该方法获得一个长度为11的list,且元素内容为空 如此copy()
List dest=Arrays.asList(new Object[src.size()]);
Collections.copy(dest,src);
面试题⭐
1、final修饰Map后,还可以继续添加元素,因为不可变的是Map对象的地址。
2、Hashtable底层使用数组+单向链表;底层用sychronized()修饰
泛型
1、泛型是指在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值或参数的类型,必须是引用数据类型
2、在集合、比较器中使用泛型。
3、iterator()
无参数,而尖括号在返回值类型的前面是泛型方法,返回iterator对象
4、Comparable
接口和Comparator
接口使用泛型,Employee
是自定义类。
public class Employee implements Comparable<Employee>{
public int compareTo(Employee e) {
return this.getName().compareTo(e.getName());
}
}
TreeSet<Employee> employees = new TreeSet<>(new Comparator<Employee>() {
@Override
public int compare(Employee o1, Employee o2) {
return 0;
}
});
}
且compare方法中正常return value返回的是从小到大的顺序
4、implements comparable<T>,也需要传入具体参数类型。
5、Object是所有引用数据类型的根,因此泛型必须是引用数据类型
6、自定义泛型类:类名前有个泛型
当子类继承泛型类时,若子类前有<E>,则为泛型类。
public class SubOrder<E> extends Order<Integer>
SubOrder<String> subOrder = new SubOrder<>();
subOrder.getE();//String
subOrder.getT();//Integer
7、下面两者的含义不太一样,一种是没有泛型,另一种是泛型的指定类型是Object
Order order = new Order();
Order<Object> order3=new Order<>();
8、当类为泛型类时,不能在类内new 泛型数组,但是可以E[] elements=(E[]) new Object[capacity];
相当于强转 底部是Object数组
为什么不能直接在类内new泛型数组? 因为创建数组的类型在Java中必须是明确的可见的,为了就是每次插入新元素会进行类型检查,但是Java在编译期间,所有的泛型信息都会被擦除,擦除后会被类型都变成Object,但无法避免可能出现转换异常的情况,因此没法new泛型数组。
9、自定义泛型方法 public <> 返回值类型 方法名(形参列表) 在返回值类型的前面有个<>
在静态方法中,不能只在方法体中使用泛型,因为泛型的确定要么在实例化对象时,要么就是抹除。
但可以使得泛型方法变成静态,且泛型方法所属的类是不是泛型类都可以
10、其中方法体的<E>表示是泛型方法,表明其中参数或者返回值类型E为泛型而不是某个自定义类。
//自定义泛型方法
//3个E:表明方法是一个泛型方法 返回值类型 形参列表
public <E> E method(E e){
return null;
}
public <E> ArrayList copyFromArrayToList(E[] arr){
return null;
}
11、Map的values中为T对象,将所有T对象转换成List,并返回
方法1:对获得的map.values进行遍历,每个加到list中
方法2:使用list.addAll(),其参数可以为Collection的对象
方法3:new ArrayList<>(),初始化Arraylist时将Collection对象作为参数传入。
//返回map中的所有T对象
public List<T> list(){
//values是可重复的无序的,因此并不是List 不能直接强转
// Collection<T> values = map.values();
// return (List<T>) values;
Collection<T> values = map.values();
// ArrayList<T> list=new ArrayList<>();
ArrayList<T> list=new ArrayList<>(values);
//方式1
// for (T t:values){
// list.add(t);
// }
// return list;
//方式2
// list.addAll(values);
// return list;
//方式3
return list;
}
12、String str="A"; str.tostring()
返回的结果是A
String[] str=new String[]{} str.toString()
返回的结果是str的地址,想要输出的结果是内容,方式1:.toString()
变成字符串再输出 方式2:Arrays.toString(str);
13、当类A是superA的子类时,G<A>和G<superA>没有多态关系。是平等的
String[] arr1=null;
Object[] arr2=null;
arr2=arr1;//基于继承性多态的使用
ArrayList<String> list1=new ArrayList<>();
ArrayList<Object> list2=new ArrayList<>();
// list2=list1;//包装里面的东西是父子类关系,但包装之后没有这层关系 此时赋值指向同一个地址
14、superA<G>和super<G>有子父关系,可以进行赋值,例如:
子可以赋值给父,但父不能赋值给子;小范围可以赋值给大范围,大范围赋值不了小范围。
List<String> list1=null;
ArrayList<String> list2=new ArrayList<>();
list1=list2;
list1.add("AA");
通配符
1、G<?>可以看成G<任意类型>类型的父类,即可以将G<任意类型>的对象赋值给G<?>类型
G<?> 只可以读取,读取之后内容的类型是Object,不可以写,除非null
List<?> list=null;
List<String> list1=new ArrayList<>();
list1.add("A");
list=list1;//直接赋值操作
//读取数据
Object o = list.get(0);//通配符的集合中,传入后读取的数据是Object型
//通配符的集合中,不能增加数据,除了特例null
list.add(null);
list1.add("B");
System.out.println(list.get(2));
2、List<? extend 指定类型> ======List<? ≤ 指定类型 >
List<? super 指定类型> ======List<? ≥ 指定类型>
3、当是 ? super 指定类型时,list中可以增加其指定类型、指定类型的子类和null
总结来说是可以赋取值范围中的最小值。
代码随想录
1、滑动窗口的模板
//[left,right)窗口左闭右开
int left=0;
int right=0;
while(right<s.length)
{
//此时先将当前right指向的内容移入窗口
移入窗口之后需要改变的变量和进行的操作
right++;
while(left<right && 窗口满足要求){
//将当前left指向的内容移出窗口
移出之后改变相关变量和进行操作
left++;
}
}
2、对于最小覆盖子串,除了使用Map外,也可以用字符的ascII码来进行计算,使用int[]存储子串中含有的字符串个数,一旦在s中发现有的话,就将int[]中对应字符的数量--,然后count--
标签:Object,Java,list,11.15,List,泛型,集合,new,元素 From: https://www.cnblogs.com/exo123/p/18539245