List
来源:互联网 发布:网络质量监控 美团 编辑:程序博客网 时间:2024/06/05 06:20
项目需求中遇到一个问题。需要将一个复杂的对象复制一个数据一样内存不一样的出来。
Java中的复制貌似是除了数据类型之外,其他的都是传递对象内存地址。当你的这个对象中嵌套了list<T>(T是一个class,不是数据类型)的时候,即便你用新的list去接收。
但是list里面的数据对象的内存地址还是一样,当你对新的list进行操作的时候。其实操作的还是老的list中的数据对象,应为他们内存地址一样。
为了避免这种情况,网上找了很多方法,有的说用clone,尝试过之后还是不行,个人觉得是对稍微简单的对象操作应该是没有问题,
如果说对象里面嵌套了list可能就不能达到预期的效果.有的说用collection.copy,但是最终还是浅拷贝,也不能达到预期效果。最终找到上面这个,简单好用,不过需要你的class能
实现Serializable接口。这个方法返回的数据对象就是一个全新的对象,内存地址不同
1.add其实不是深度复制,而是添加引用指向对象
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public abstract class BeanCloneUtil { @SuppressWarnings("unchecked") public static <T> T cloneTo(T src) throws RuntimeException { ByteArrayOutputStream memoryBuffer = new ByteArrayOutputStream(); ObjectOutputStream out = null; ObjectInputStream in = null; T dist = null; try { out = new ObjectOutputStream(memoryBuffer); out.writeObject(src); out.flush(); in = new ObjectInputStream(new ByteArrayInputStream(memoryBuffer.toByteArray())); dist = (T) in.readObject(); } catch (Exception e) { throw new RuntimeException(e); } finally { if (out != null) try { out.close(); out = null; } catch (IOException e) { throw new RuntimeException(e); } if (in != null) try { in.close(); in = null; } catch (IOException e) { throw new RuntimeException(e); } } return dist; } }
Java集合主要分为三种类型:Set(集)、List(列表)和Map(映射)。
下面具体说下集合(Collection:List、Set,Map:HashMap、TreeMap)
二、细说Java集合
List特点:元素有序,元素可重复
Map特点:元素按键值对存储,无序(key不可重复,重复会覆盖之前的,value可以重复)
Set特点:元素无放入顺序,元素不可重复(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的)
LinkedList:底层基于链表实现。链表增删快,查找慢 。
排序:
数组:
一.Array 排序
Arrays.sort(int[] a)中的排序是用的是快速排序,一般顺序是升序的,字母也是A~Z这种排序的。
Arrays.sort(T[], Comparator < ? super T > c),自定义排序,自定义算法写在第二个参数里面。
Comparable和Comparator区别
Comparable可以认为是一个内比较器,自然排序 ,Comparator可以认为是是一个外比较器,比较器排序
Comparable:假设我们通过 x.compareTo(y) 来“比较x和y的大小”。
若返回“负数”,意味着“x比y小”;返回“零”,意味着“x等于y”;返回“正数”,意味着“x大于y”。
Comparator:int compare(T o1, T o2) 是“比较o1和o2的大小”。返回“负数”,意味着“o1比o2小”;返回“零”,意味着“o1等于o2”;返回“正数”,意味着“o1大于o2”。
demo:
Comparable示例程序
import java.util.ArrayList;import java.util.Collections;import java.util.List;public class StudentComparable implements Comparable<StudentComparable> { private String name; private int age; public StudentComparable(String name, int age) { this.name = name; this.age = age; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public int getAge() { return age; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } StudentComparable that = (StudentComparable) o; if (getAge() != that.getAge()) { return false; } return getName() != null ? getName().equals(that.getName()) : that.getName() == null; } @Override public int hashCode() { int result = getName() != null ? getName().hashCode() : 0; result = 31 * result + getAge(); return result; } @Override public int compareTo(StudentComparable o) { if (this.name.compareTo(o.getName()) > 0) { return 1; }else if (this.name.compareTo(o.getName()) < 0) { return -1; } return 0; } @Override public String toString() { return "StudentComparable{" + "name='" + name + '\'' + ", age=" + age + '}'; } public static void main(String[] args) { List<StudentComparable> list = new ArrayList<>(); list.add(new StudentComparable("Jack", 16)); list.add(new StudentComparable("Mike", 25)); list.add(new StudentComparable("Summer", 17)); list.add(new StudentComparable("Bob", 19)); Collections.sort(list); for (StudentComparable stu : list) { System.out.println(stu); } }}
Comparator示例代码
import java.util.*;class A implements Comparator<String> { @Override public int compare(String s1, String s2) { int len1 = s1.length(); int len2 = s2.length(); if (len1 > len2) { return 1; }else if (len1 < len2) { return -1; }else { return 0; } }}public class ComparatorTest { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("cat"); list.add("fish"); list.add("dog"); list.add("panda"); Collections.sort(list, new A()); System.out.println(list); }}
注意
在Comparable接口的实现类里,我们要必须重写compareTo()方法,看需求是否需要重写hashCode()方法和equals()方法 。
在Comparator接口的实现类里,我们必须重写compare()方法,看需求是否需要重写hashCode()方法和equals()方法 。
其实上述的hashCode()方法和equals()方法不重写也是可以的。
根据这两个规范,可以得到如下推论:
1、如果两个对象equals,Java运行时环境会认为他们的hashcode一定相等。
2、如果两个对象不equals,他们的hashcode有可能相等。
3、如果两个对象hashcode相等,他们不一定equals。
4、如果两个对象hashcode不相等,他们一定不equals。
这样我们就可以推断Java运行时环境是怎样判断HashSet和HastMap中的两个对象相同或不同了。我的推断是:先判断hashcode是否相等,再判断是否equals。
这方面的文章参考:http://blog.csdn.net/chy800/article/details/7239838
区别:
Comparable接口是在集合内部定义的方法实现的排序。
Comparator接口是在集合外部实现的排序。
简单来说,comparable接口是通过类自己完成比较,而comparator接口是通过外部程序实现比较。
结论
1、如果实现类没有实现Comparable接口,又想对两个类进行比较(或者实现类实现了Comparable接口,但是对compareTo方法内的比较算法不满意),那么可以实现Comparator接口,自定义一个比较器,写比较算法
2、实现Comparable接口的方式比实现Comparator接口的耦合性 要强一些,如果要修改比较算法,要修改Comparable接口的实现类,而实现Comparator的类是在外部进行比较的,不需要对实现类有任何修 改。从这个角度说,其实有些不太好,尤其在我们将实现类的.class文件打成一个.jar文件提供给开发者使用的时候。实际上实现Comparator 接口的方式后面会写到就是一种典型的策略模式。即Comparator好处是可以不改变类的情况下去排序(如某个jar包里面的类没有实现Comparable接口但是我们有需要去排序那么COmparator就派上用场了),而Comparable的话,对象需要去实现Comparable接口
如果同时有自然排序和比较器排序,以比较器排序为主
比较标准的写法。判空
Collections.sort(riskFactorNameList, new Comparator<RiskFactorName>() { @Override public int compare(RiskFactorName o1, RiskFactorName o2) { if(o1.getSortNo() == null) { return -1; } if(o2.getSortNo() == null) { return 1; } if (o1.getSortNo() > o2.getSortNo()) { return 1; } if (o1.getSortNo() == o2.getSortNo()) { return 0; } if (o1.getSortNo() < o2.getSortNo()) { return -1; } return 0; }});
- @Override
- public int compareTo(Object o) {
- if(this ==o){
- return 0;
- }
- else if (o!=null && o instanceof User) {
- User u = (User) o;
- if(id<=u.id){
- return -1;
- }else{
- return 1;
- }
- }else{
- return -1;
- }
- }
使用 String.compareTo 方法:
1、如果字符串相等返回值0但是可能受到语言的影响,所以区分语言
2、如果第一个字符和参数的第一个字符不等,结束比较,返回他们之间的差值(ascii码值)(负值前字符串的值小于后字符串,正值前字符串大于后字符串)
3、如果第一个字符和参数的第一个字符相等,则以第二个字符和参数的第二个字符做比较,以此类推,直至比较的字符或被比较的字符有一方全比较完,这时就比较字符的长度.
例:
String s1 = "abc";
String s2 = "abcd";
String s3 = "abcdfg";
String s4 = "1bcdfg";
String s5 = "cdfg";
System.out.println( s1.compareTo(s2) ); // -1 (前面相等,s1长度小1)
System.out.println( s1.compareTo(s3) ); // -3 (前面相等,s1长度小3)
System.out.println( s1.compareTo(s4) ); // 48 ("a"的ASCII码是97,"1"的的ASCII码是49,所以返回48)
System.out.println( s1.compareTo(s5) ); // -2 ("a"的ASCII码是97,"c"的ASCII码是99,所以返回-2)
Collator 类执行区分语言环境的 String 比较。使用此类可为自然语言文本构建搜索和排序例程。
public
class
StudentComparator
implements
Comparator<Student> {
public
int
compare(Student o1, Student o2) {
if
(o1.getScore() != o2.getScore()) {
return
o2.getScore() - o1.getScore();
}
else
{
Collator instance = Collator.getInstance(Locale.CHINA);
return
instance.compare(o1.getName(), o2.getName());
}
}
}
比较大小的时候equals里面做判空。
@Overridepublic boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; RiskFactorName that = (RiskFactorName) o; return name != null ? name.equals(that.name) : that.name == null;}
- List
- list
- List
- LIST
- list
- list
- List
- list
- list
- List
- list
- LIST
- List
- List
- List
- list
- list
- list
- 用javascript源码打印页面
- Entity FrameWork介绍
- 线程死锁
- 链表插入排序
- solr 搜索建议suggest
- List
- MPI并行程序设计学习整理
- 移动页面HTML5自适应手机屏幕宽度
- tomcat通过分配不同端口部署多个项目
- linux学习之ISCSI网络共享服务
- 安装activex控件(64位机器MSComm32)
- 记录AWS使用产生的EBS费用
- spark源码之RDD(1)partition、dependence、persist
- 类加载机制及类加载器加载Class流程