我有一个Map在应用程序启动期间填满的.在执行应用程序期间,它不会在以后更改.之后,此映射仅用于迭代其中的所有元素.Map我应该选择哪种具体实施方案?HashMap或TreeMap或LinkedHashMap?
更新广告
订单无关紧要.唯一重要的是快速迭代所有元素(比如6000个元素).
在阅读Marker接口时,我偶然发现了以下网站:第37项:使用标记接口来定义类型
在这里,根据Joshua Bloch,Marker接口相对于Marker注释有两个优点.
标记接口定义由标记类的实例实现的类型; 标记注释没有.如果使用标记注释,则此类型的存在允许您在编译时捕获错误,直到运行时才能捕获这些错误.
标记接口相对于标记注释的另一个优点是可以更精确地定位它们.如果使用target声明注释类型
ElementType.TYPE,则可以将其应用于任何类或接口.假设您有一个仅适用于特定接口实现的标记.如果将其定义为标记接口,则可以使其扩展到适用的唯一接口,从而保证所有标记类型也是适用的唯一接口的子类型.
好的,第一点被理解,但我不确定我是否正确理解第二点:
如果使用target声明注释类型
ElementType.TYPE,则可以将其应用于任何类或接口.
同样,如果我有一个标记接口,那么它也可以应用于任何类或接口.是不是对标记注释和标记界面说了同样的话?如何更精确地定位标记界面?
第二点还提到:
您可以[标记接口]扩展适用的唯一接口,保证所有标记类型也是适用的唯一接口的子类型.
你不能通过使用@Inherited元注释来实现注释吗?
setter方法是否仅用于设置属性的值,因为它作为参数传递?在将值赋给属性之前,我们可以编写一些验证逻辑吗?
Liskov替代原理对派生类中的方法签名施加的规则之一是:
子类型中方法参数的矛盾性。
如果我理解正确的话,就是说派生类的重写函数应允许使用自变量(超类型自变量)。但是,我不明白这条规则背后的原因。由于LSP主要讨论动态地将类型与那里的子类型(而不是超类型)进行绑定以实现抽象,因此让超类型作为派生类中的方法参数对我来说是很困惑的。我的问题是:
我有以下几种情况:我在这里展示的是简单的代码形式,以澄清我的担忧:
public void callMe()
{
AtomicInteger howManyOdds = new AtomicInteger(0);
AtomicInteger howManyEvens = new AtomicInteger(0);
loopThrough(100,howManyOdds,howManyEvens);
System.out.println(howManyOdds.get()+" "+howManyEvens.get());
}
private void loopThrough(int counter,AtomicInteger howManyOdds,AtomicInteger howManyEvens)
{
for(int i = 1 ; i <= counter ;i++)
{
if(i%2 == 0)
howManyEvens.getAndAdd(1);
else
howManyOdds.getAndAdd(1);
}
}
Run Code Online (Sandbox Code Playgroud)
我知道它可以通过int[]但它看起来有点奇怪.在这种情况下,AtomicInteger是Mutable Integer的良好替代品吗?如果不是那么为什么?
好吧,考虑Immutable下面给出的不可变类:
public final class Immutable
{
final int x;
final int y;
public Immutable(int x,int y)
{
this.x = x;
this.y = y;
}
//Setters
public int getX()
{
return this.x;
}
public int getY()
{
return this.y;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我创建的对象Immutable的一类Sharable,其目的是要由多个线程共享:
public class Sharable
{
private static Immutable obj;
public static Immutable getImmutableObject()
{
if (obj == null) --->(1)
{
synchronized(this)
{
if(obj == null)
{
obj = new Immutable(20,30); ---> (2)
}
} …Run Code Online (Sandbox Code Playgroud) 对于以下代码:
ArrayList<String> ar = new ArrayList<String>();
ar.add(45);
Run Code Online (Sandbox Code Playgroud)
和
ArrayList<String> ar = new ArrayList();
ar.add(45);
Run Code Online (Sandbox Code Playgroud)
我在编译时遇到错误ar.add(45):
cannot find symbol
symbol : method add(int)
location: class java.util.ArrayList<java.lang.String>
al.add(45);
^
Run Code Online (Sandbox Code Playgroud)
这两段代码都无法输入无效的内容.那么为什么编译器会针对第二段代码提出未经检查或不安全操作的警告?
volatile写入是否确保在一个线程中的任何写入(非易失性/易失性写入)在其他线程可见之前发生?
下面给出的代码总是会产生90,80输出吗?
public class MyClass
{
private boolean flag = false;
private volatile int volatileInt = 0;
private int nonVolatileInt = 0;
public void initVariables()
{
nonVolatileInt = 90; // non-volatile write
volatileInt = 80; // volatile write
flag = true; // non-volatile write
}
public void readVariables()
{
while (flag == false)
{}
System.out.println(nonVolatileInt + ","+ volatileInt);
}
public static void main(String st[])
{
final MyClass myClass = new MyClass();
Thread writer = new Thread( new Runnable() …Run Code Online (Sandbox Code Playgroud) java ×7
annotations ×1
collections ×1
concurrency ×1
generics ×1
immutability ×1
interface ×1
iteration ×1
liskov-substitution-principle ×1
mutable ×1
non-volatile ×1
oop ×1
volatile ×1