So I've come accross this bit of code while scavaging through org.eclipse.ui.internal.Workbench:
final boolean[] initOK = new boolean[1];
if (getSplash() != null) {
final boolean[] initDone = new boolean[] { false };
final Throwable[] error = new Throwable[1];
Thread initThread = new Thread() {
/*
* (non-Javadoc)
*
* #see java.lang.Thread#run()
*/
public void run() {
try {
// declare us to be a startup thread so that our
// syncs will be executed
UISynchronizer.startupThread.set(Boolean.TRUE);
initOK[0] = Workbench.this.init();
} catch (Throwable e) {
error[0] = e;
} finally {
initDone[0] = true;
display.wake();
}
}
};
initThread.start();
..............
}
What's the purpose of creating arrays with just one element? Is it faster? I'm definitly missing something here.
The advantage of using this approach is that the arrays cannot be modified (because they are final), however, their content can be changed.
A useful example is that you can use these arrays and modify their first entry in anonymous inner classes without having to make them (static) fields.
As stated in the comments above, another use-case is that this array can be used to pass it to a method expecting an array type.
Related
I'm new to this site, so please feel free to correct me if there's anything wrong about my question or the style of the question.
I need to implement the Iterable Interface in my ShareCollection class, so that I can iterate over all the shares in this class. When I'm testing my class with the sample data it always hands back '0' as size, even though there are (in my example) two shares in my collection.
Here's the code of the class + one sample method which hands back an error:
public class ShareCollection implements Iterable<Share>{
private HashSet<Share> shares;
public ShareCollection() {
this.shares = new HashSet<Share>();
}
public ShareCollection(Collection<Share> shares) {
for (Share s : shares) {
HashSet<Share> checkSet = new HashSet<Share>(shares);
checkSet.remove(s);
if (checkSet.contains(s)) {
throw new IllegalArgumentException("There can't be two shares with the same name!");
}
}
this.shares = new HashSet<Share>(shares);
}
public boolean add(Share share) {
if (share == null) {
throw new NullPointerException("share isnt allowed to be null!");
}
return shares.add(share);
}
#Override
public Iterator<Share> iterator() {
return new HashSet<Share>(shares).iterator();
}
}
Here's the main method with the sample data I'm using:
public static void main(String[] args) {
Share s1 = new Share("s1", new ArrayList<>());
Share s2 = new Share("s2", new ArrayList<>());
ShareCollection sc = new ShareCollection()
sc.add(s1);
sc.add(s2);
int counter = 0;
for (Share s : sc) {
counter++;
}
System.out.print("Counter: " + counter + "\n");
System.out.print("Size: " + sc.size());
}
Here's the output for the main-method:
Counter: 2
Size: 0
Here's the error for the 'add'-method:
java.lang.AssertionError: ShareCollection#size should give 1 for a collection with 1 elements.
Expected: <1>
but: was <0>
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
at org.junit.Assert.assertThat(Assert.java:956)
at jpp.marketanalysis.tests.data.TestShareCollection.hasElements(TestShareCollection.java:158)
at jpp.marketanalysis.tests.data.TestShareCollection.testAdd(TestShareCollection.java:55)
Thank you in advance for your answers!
Update:
Exchanged the ArrayList with a HashSet (see #SeanPatrickFloyd's first answer)
Possible error: Does your Share class override the .equals() method?
Because ArrayList.contains() delegates to .equals()
Also, I see at least two problems with your code:
An ArrayList is very bad at a .contains() lookup (O(n)). You should use a HashSet instead (in that case you'd need to override both .equals() and .hashCode() in your Share class), it gives you O(1) and handles the .add() method properly for you as well
The Iterator you are returning is the ArrayList's original iterator, which makes your code vulnerable in several ways, including ConcurrentModificationException if you add something while iterating, but also mutation, if someone calls .remove() on the iterator. I'd suggest you make a defensive copy of the collection and use that iterator.
Here's your code rewritten accordingly:
public class ShareCollection implements Iterable<Share>{
private final Set<Share> shares;
public ShareCollection() {
this.shares = new HashSet<>();
}
public ShareCollection(Collection<Share> shares) {
this.shares = new HashSet<>(shares);
}
public boolean add(Share share) {
if (share == null) {
throw new NullPointerException("share isnt allowed to be null!");
}
return shares.add(share);
}
#Override
public Iterator<Share> iterator() {
return new HashSet<>(shares).iterator();
}
}
I want to return final ArrayList in Android, but the ArrayList always return size 0. I do add() in inner class, but the return log faster then inner class log.
My code :
public static ArrayList<SportsData> getSportsFavorite(){
final ArrayList<SportsData> sportsDatas = new ArrayList<>();
DBRequestData reqData = new DBRequestData();
reqData.cmdId = CmdConst.DISCIPLINE_DATA.SELECT_ALL.ordinal();
DisciplineCmd cmd = new DisciplineCmd();
cmd.requestCmd(reqData, new OnDatabaseListener() {
#Override
public void onDBResponse(BaseCmd command) {
if (command == null || command.getResponseData() == null) {
return;
}
ArrayList<DisciplineTable> dbDisciplineList = command.getResponseData().disciplineTableList;
if (dbDisciplineList == null) {
return;
}
if(sportsFavoriteList.size() == 0) {
init();
}
for (DisciplineTable disciplineData : dbDisciplineList){
for (String favoriteCode : sportsFavoriteList){
String[] codeArr = favoriteCode.split("[|]");
String discCode = codeArr[0];
String compeCode = codeArr[1];
if(disciplineData.disciplineCode.equals(discCode) && disciplineData.competitionCode.equals(compeCode)){
int imgRes = SportsUtil.getSportsImgResource(disciplineData.disciplineCode, disciplineData.competitionCode);
sportsDatas.add(new SportsData(imgRes, disciplineData));
Log.e("SportsUtil", "inner Size : "+sportsDatas.size()); // RETURN SECOND -
}
}
}
}
});
Log.e("SportsUtil", "Return Size : "+sportsDatas.size()); //RETURN FIRST
return sportsDatas;
}
Logcat :
07-22 14:33:32.337 651-651/com.samsung.riowow.result E/SportsUtil﹕ Return Size : 0
07-22 14:33:32.347 651-651/com.samsung.riowow.result E/SportsUtil﹕ inner Size : 1
07-22 14:33:32.347 651-651/com.samsung.riowow.result E/SportsUtil﹕ inner Size : 2
07-22 14:33:32.347 651-651/com.samsung.riowow.result E/SportsUtil﹕ inner Size : 3
07-22 14:33:32.347 651-651/com.samsung.riowow.result E/SportsUtil﹕ inner Size : 4
07-22 14:33:32.347 651-651/com.samsung.riowow.result E/SportsUtil﹕ inner Size : 5
The result that want to is ArrayList what size is 5. But always return ArrayList's size is 0. Please help me :) Thanks.
SOLVE
If you want to know reason of this situation, please check the Florian Schaetz's answer.
My solution for this, I change the return type of method and add interface listener parameter. Please check my solution.
First, Create interface and method has parameter you want to return.
public static interface SportsDataListener{
public void onSportsDataResponse(ArrayList<SportsData> sportsDataList);
}
Second, Change method's return type to void and add interface parameter. And call interface's method instead return
public static void getSportsFavorite(final SportsDataListener listener){
final ArrayList<SportsData> sportsDatas = new ArrayList<>();
DBRequestData reqData = new DBRequestData();
reqData.cmdId = CmdConst.DISCIPLINE_DATA.SELECT_ALL.ordinal();
DisciplineCmd cmd = new DisciplineCmd();
cmd.requestCmd(reqData, new OnDatabaseListener() {
#Override
public void onDBResponse(BaseCmd command) {
if (command == null || command.getResponseData() == null) {
return;
}
ArrayList<DisciplineTable> dbDisciplineList = command.getResponseData().disciplineTableList;
if (dbDisciplineList == null) {
return;
}
if(sportsFavoriteList.size() == 0) {
init();
}
for (DisciplineTable disciplineData : dbDisciplineList){
for (String favoriteCode : sportsFavoriteList){
String[] codeArr = favoriteCode.split("[|]");
String discCode = codeArr[0];
String compeCode = codeArr[1];
if(disciplineData.disciplineCode.equals(discCode) && disciplineData.competitionCode.equals(compeCode)){
int imgRes = SportsUtil.getSportsImgResource(disciplineData.disciplineCode, disciplineData.competitionCode);
sportsDatas.add(new SportsData(imgRes, disciplineData));
}
}
}
listener.onSportsDataResponse(sportsDatas);
}
});
}
Last, You can use
SportsUtil.getSportsFavorite(new SportsUtil.SportsDataListener() {
#Override
public void onSportsDataResponse(ArrayList<SportsData> sportsDataList) {
//Some action you want to do. You can use parameter
}
}
Seems pretty asynchronous to me. You are calling a method and give it a callback that will be called AFTER the action is done, here probably after the database returns. The main code isn't blocked, but goes one, while the other OnDatabaseListener waits in the background for an answer, thus your method returns the original list which then suddenly grows as the database answer returns.
I guess your onDBResponse method is running in different thread. You are modifying the arraylist inside that method. So before modifying the arraylist is getting returned in this case. Always it will give you arraylist of size 0.
You should provide a callback interface to getSportsFavorite() which takes the array list as a parameter, and call it on the completion of your OnDatabaseListener method.
Yes the problem is because your onDBResponse() is called after the method has returned the array list. You should suspect this from the order of your logs.
SOLUTION
Assuming that it is your requirement that you get the array list synchronously. Just before your cmd.requestCmd do:
final Object lock = new Object();
then add this before your return sportsDatas;:
synchronized(lock) {
lock.wait();
}
and in the end of onDBResponse() add:
synchronized(lock) {
lock.notify();
}
Essentially, now your method will wait until the response from DB has come before returning the array list.
You will need to catch the InterruptedException and that's it!
Hope it helps! :)
you must run onDBResponse once at least.
public static void main(String[] args) {
final List<String> sportsDatas = new ArrayList<>();
Commond commond = new Commond() {
#Override
public void onDBResponse() {
sportsDatas.add("1");
sportsDatas.add("2");
sportsDatas.add("3");
}
};
System.out.println(sportsDatas.size());
commond.onDBResponse();
System.out.println(sportsDatas.size());
}
}
output:
0
3
The situation (UML given below): A java package shall have a class Process that runs a calculation in a loop within a thread and notifies observers about the result of that calculation. A new calculation is initiated bei adding a value from outside the class to a queue the thread can read:
public class Process
{
/* ... */
Thread th;
BlockingQueue queue = new ArrayBlockingQueue(10);
public void calc()
{
th = new Thread(new Runnable()
{
public void run()
{
while (!Thread.currentThread().isInterrupted())
{
try
{
Integer value = (Integer) queue.take();
List<Float> result = calculator.calcAllResults(value);
/* ... Do something with result ...*/
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}).start();
}
public void addValue(Integer value)
{
queue.add(value);
}
/* ... */
}
The calculation itself in calcAllResults(int value) is as follows: The calculator object has a (interchangeable by a config file, not fixed) list of "smaller calculators" that calculate exactly one Float in the result list. Now, the calculator object first gathers some data and then just runs all the small calculators in a loop:
public class Calculator
{
/* ... */
private DataGatherer1 dataGatherer1;
public List<Float> calcAllResults(int value)
{
List<Float> result = new List<Float>();
DataType1 dt1 = dataGatherer1.getData(value);
for (int i = 0; i < calculators.size(); i++)
{
result.add(calculators.get(i).calcSingleResult(dt1));
}
}
/* ... */
}
My Problem: For the moment there is only one way to calculate the result, but in future there will be more. That means: Currently, the small calculator objects that run calcSingleResult depend on data of type DataType1 (see listing above), but in future there might be another set of calculator objects that depend on data of type DataType2. Of course, then there must be another class, DataGatherer2, that gathers data of that new type. In order to make the code expandable in the way mentioned, I thought of two options how to design the package. But none of them seem to be satisfactory for the reasons mentioned below. To make the two approches clear, I made two UML-Diagrams:
Design1
Design2
Design 1:
The calculator for calculating the result list has an AbstractDataGatherer object which can be of type DataGatherer1 or DataGatherer2 (depending on the state of the program). As both data types (DataType1 and DataType2) are of type AbstractDataObject, the method calcAllResults() can have all the logic for gathering data and calculation (an advantage of this design (?)), no matter what set of CalcType's is in its calculator list:
public class Calculator
{
/* ... */
private AbstractDataGatherer dataGatherer;
private List<AbstractCalculationType> calculators;
public List<Float> calcAllResults(int value)
{
List<Float> result = new List<Float>();
AbstractDataObject dt = dataGatherer.getData(value);
for (int i = 0; i < calculators.size(); i++)
{
result.add(calculators.get(i).calcSingleResult(dt));
}
}
/* ... */
}
The disadvantage is (in my eyes) that a specific CalcType expects a specific DataType in its calcSingleResult()-routine. So AbstractDataObject dt must be casted. For example:
public class CalcType1A extends AbstractCalculationType
{
/* ... */
private DataType1 data;
public float calcSingleResult(AbstractDataObject data)
{
this.data = (DataType1) data;
}
/* ... */
}
Design 2:
The calcAllResults()-method is now inside an object of type AbstractCalculationStrategy. From this abstract class two (in future possibly more) subclasses exist: CalculationStrategy1 and CalculationStrategy2. Both define calcAllResults() alone. For example:
public class CalculationStrategy1 extends AbstractCalculationStrategy
{
/* ... */
private DataGatherer1 dataGatherer1;
private List<AbstractCalculationType1> calculators;
public float calcAllResult(int value)
{
List<Float> result = new List<Float>();
DataType1 dt1 = dataGatherer1.getData(value);
for (int i = 0; i < calculators.size(); i++)
{
result.add(calculators.get(i).calcSingleResult(dt1));
}
}
/* ... */
}
(The same for CalculationStrategy2, but with a DataGatherer2 object and AbstractCalculationType2 objects instead.)
This is basically the situation from above where only one calculation type existed. The advantage here is that each strategy must gather a specific data type that its calculator objects really wants (no cast). The disadvantage is that you have duplicate code: The logic in the method calcAllResult() is the same (or: must in future be implemented in the same way) for both (in future possible more) calculation strategies. Additionally the UML diagram shows that there is a symmetry that I would like to prevent with OOP-means, because OOP is made to prevent duplicate code / symmetry, right?
So, what is the best design? Or are both options not okay?
I've already made another question close to this one several minutes ago, and there were good answers, but it was not what I was looking for, so I tried to be a bit clearer.
Let's say I have a list of Thread in a class :
class Network {
private List<Thread> tArray = new ArrayList<Thread>();
private List<ObjectInputStream> input = new ArrayList<ObjectInputStream>();
private void aMethod() {
for(int i = 0; i < 10; i++) {
Runnable r = new Runnable() {
public void run() {
try {
String received = (String) input.get(****).readObject(); // I don't know what to put here instead of the ****
showReceived(received); // random method in Network class
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
tArray.add(new Thread(r));
tArray.get(i).start();
}
}
}
What should I put instead of ** ?
The first thread of the tArray list must only access the first input of the input list for example.
EDIT : Let's assume my input list has already 10 elements
It would work if you put i. You also need to add an ObjectInputStream to the list for each thread. I recommend you use input.add for that purpose. You also need to fill the tArray list with some threads, use add again there.
Here's the solution:
private void aMethod() {
for(int i = 0; i < 10; i++) {
final int index = i; // Captures the value of i in a final varialbe.
Runnable r = new Runnable() {
public void run() {
try {
String received = input.get(index).readObject().toString(); // Use te final variable to access the list.
showReceived(received); // random method in Network class
} catch (Exception exception) {
exception.printStackTrace();
}
}
};
tArray.add(new Thread(r));
tArray.get(i).start();
}
}
As you want each thread to access one element from the input array you can use the value of the i variable as an index into the list. The problem with using i directly is that an inner class cannot access non-final variables from the enclosing scope. To overcome this we assign i to a final variable index. Being final index is accessible by the code of your Runnable.
Additional fixes:
readObject().toString()
catch(Exception exception)
tArray.add(new Thread(r))
Ok, here is the code and then the discussion follows:
public class FlatArrayList {
private static ArrayList<TestWrapperObject> probModel = new ArrayList<TestWrapperObject>();
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int [] currentRow = new int[10];
int counter = 0;
while (true) {
for (int i = 0; i < 10; i++) {
currentRow[i] = probModel.size();
}
TestWrapperObject currentWO = new TestWrapperObject(currentRow);
probModel.add(counter, currentWO);
TestWrapperObject testWO = probModel.get(counter);
// System.out.println(testWO);
counter++;
if (probModel.size() == 10) break;
}
// Output the whole ArrayList
for (TestWrapperObject wo:probModel) {
int [] currentTestRow = wo.getCurrentRow();
}
}
}
public class TestWrapperObject {
private int [] currentRow;
public void setCurrentRow(int [] currentRow) {
this.currentRow = currentRow;
}
public int [] getCurrentRow() {
return this.currentRow;
}
public TestWrapperObject(int [] currentRow) {
this.currentRow = currentRow;
}
}
What is the above code supposed to do? What I am trying to do is load an array as a member of some wrapper object (TestWrapperObject in our case). When I get out of the loop,
the probModel ArrayList has the number of elements it is supposed to have but all have the same value of the last element (an array of size 10 with each item equal to 9). This is not the case inside the loop. If you perform the same "experiment" with a primitive int value everything works fine. Am I missing something myself regarding arrays as object members? Or did I just encounter a Java bug? I am using Java 6.
You are only creating one instance of the currentRow array. Move that inside the row loop and it should behave more like you expect.
Specifically, the assignment in setCurrentRow does not create a copy of the object, but only assigns the reference. So each copy of your wrapper object will hold a reference to the same int[] array. Changing the values in that array will make the values appear to change for all other wrapper objects that hold a reference to the same instance of the array.
i don' t want to sound condescending, but always try to remember tip #26 from the excellent pragmatic programmer book
select isn't broken
it is very rare to find a java bug. keeping this in mind often helps me to look over my code again, turn it around, and shake out the loose bits until i finally discover where i was wrong. of course asking for help early enough is very encouraged, too :)