Creating multiple Java objects inside Loop and using all outside - java

I want to create multiple objects inside while loop and access all objects outside in JAVA 8.
Currently using a list to store the obects, but all objects get replaced by one last object (last created).
I have tried initializing list inside try, outside try, nothing works.
Here is my test1.java,
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class test1 {
public static void main(String[] args){
try {
List<test2> objList=new ArrayList<>();
BufferedReader encReader = new BufferedReader(new FileReader("./asd.txt"));
String eachLine;
while ((eachLine = encReader.readLine()) != null) {
String[] data = eachLine.split("\\|");
if(true){
objList.add(new test2(data[0], data[1]));
}
} // While ends here
objList.forEach(x -> x.printEncLoc());
}catch (IOException e) {
e.printStackTrace();
}
}
}
Here is my test2.java,
public class test2 {
private static String s1;
private static String s2;
test2(String s1new, String s2new){
s1=s1new;
s2=s2new;
}
public static void printEncLoc(){
System.out.println("s1:"+s1+" s2:"+s2);
}
}
Here is my input file example (asd.txt)
hello|123
qwe|klj
It calls only the last object's printEncLoc function each time in the forEach line.
It prints output as follows.
s1:qwe s2:klj
s1:qwe s2:klj
What is the problem here?

You made the properties in test2 static, this means all instances share the same properties. So when you change them for the 2nd row, the 1st row changes as well.
Remove the 'static' from s1 and s2, and from your printEncLoc() method and your code works.
EDIT: See https://www.baeldung.com/java-static for more on how static works

Related

How can I ensure that every thread is working on the same object?

How can I ensure that every thread is working on the same object? We're executing regression on 8 threads parallel. I want to store thread-specific logs in a map, then, after run, do something with the data inside it.
public class Foo {
// map with thread name as a key and queue to keep its logs
public static final Map<String, LinkedList<String>> foofoo = new ConcurrentHashMap<>();
public static void addToQueue(String threadName, String log) {
//some logic here to add log to proper queue
}
}
I want to make sure that whenever any of running threads invokes:
Foo.addToQueue("foo", "fooo");
it is accessing the same map.
Thank you for your responses. I'm kind of confused with multi threading, sorry if the question is a bit dumb.
Have a nice day! :)
Edit: in the sample up there I've used final keyword when initializing this object, because I know that it blocks objects reference. However does it solve my problem? Is there any better approach?
You can use the synchronised keyword in your method signature. When a synchronised method is called from a thread, it (the thread) automatically acquires a lock on the shared object. So what you can do is make the addToQueue method synchronised. Read more.
Alternatively, Check this out. It is quite an informative thread on Collections.synchronisedList. Have a working example also.
My understanding
Aggregate information per thread
Collect this aggregated data in the main thread
Sample Code
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class ThreadParallel {
public static void main(String[] args) {
List<Integer> input = IntStream.range(0, 100).boxed().collect(Collectors.toList());
class ThreadSpecific {
final String threadName;
final String num;
ThreadSpecific(int num) {
threadName = Thread.currentThread().getName();
this.num = Integer.toString(num);
}
public String getThreadName() {
return threadName;
}
public String getNums() {
return num;
}
}
Map<String, List<String>> result = input.parallelStream()
.map(i -> new ThreadSpecific(i))
.collect(Collectors.groupingByConcurrent(ThreadSpecific::getThreadName,
Collectors.mapping(ThreadSpecific::getNums, Collectors.toList())));
System.out.println(result);
}
}
Alternatively, if the inner aggregated object is list(or collection), then try something like:
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class ThreadParallel {
public static void main(String[] args) {
List<Integer> input = IntStream.range(0, 100).boxed().collect(Collectors.toList());
class ThreadSpecific {
final String threadName;
final List<String> nums;
ThreadSpecific(int num) {
threadName = Thread.currentThread().getName();
this.nums = new ArrayList<>();
nums.add(Integer.toString(num));
}
public String getThreadName() {
return threadName;
}
public List<String> getNums() {
return nums;
}
}
Map<String, List<String>> result = input.parallelStream()
.map(i -> new ThreadSpecific(i))
.collect(Collectors.groupingByConcurrent(ThreadSpecific::getThreadName,
Collectors.mapping(ThreadSpecific::getNums,
Collectors.collectingAndThen(Collectors.toList(), nums -> nums.stream()
.flatMap(List::stream).collect(Collectors.toList())
))));
System.out.println(result);
}
}
Notes
Edit: in the sample up there I've used final keyword when initializing this object, because I know that it blocks objects reference. However does it solve my problem? Is there any better approach?
The purpose of final in reference variables are
1. Catches any accidental/unexpected reassignment to the reference variable (only reference variable is immutable)
2. The immutable property of reference variable ensures the `L`[123] caches will maintain a consistent state of this reference variable in multithreaded execution.(possibly in single threaded execution with multiple cpus).
3. This feature avoids the need for `volatile`

How do i make a static reference to a non-static method?

import java.util.Iterator;
import java.util.ArrayList;
import java.util.Arrays;
class Main {
public static void main(String[] args) {
ArrayList<String> original = new ArrayList<>(Arrays.asList("afd", "asdf", "aavdd", "sajf", "adnf", "afd", "fjfn"));
String find = "afd";
String replaceWith = "asd";
System.out.println(replaceIt(original, find, replaceWith));
}
public ArrayList<String> replaceIt(ArrayList<String> original, String find, String replaceWith){
ArrayList<String> newList = new ArrayList<String>();
for(int y = 0; y<original.size(); i++){
if(!original.get(y).equals(find))
newList.set(y, original.get(y));
newList.set(y, replaceWith);
}
original = newList;
return original;
}
}
How do i call the replaceIt method? I'm confused and I need to make it so it prints the output of that function. I'm so confused somebody please help.
public ArrayList<String> replaceIt() is an instance method, it is only called from Main instances/objects.
public static void main is a static method of class Main, static methods can’t access instance methods and instance variables directly.
Therefor, to call replaceIt() method from static main method, make replaceIt() static.
public static ArrayList<String> replaceIt(/*arguments*/){
//your code goes here
}
Having non-static method in Main is a little odd. It's not like you are going to construct new instances of Main (say, the same way you would construct new instances of a Person class).
These type of generic helpers/utils functions usually go into some sort Utils.java or Helpers.java class, and are declared as static in these files. This way you would be able to invoke: Utils.replaceIt(original, find, replaceWith));
Because replaceIt() is an instance method, you simply need to create an instance of the Main class to call it -
public static void main(String[] args) {
...
Main m = new Main();
System.out.println(m.replaceIt(original, find, replaceWith));
}

Syntax error when declaring array in java

I'm trying to declare an array in java as part of a tic-tac-toe game, but I get syntax error when I do this:
package tictactoe;
import java.util.Random;
import java.util.Scanner;
public String a[] = new String[9];
a[0]="";
public class Board {
I thought this was the correct way to declare an array, and all the examples I look at confirm it, so why do I get a syntax error?
You need to put the declaration of your array inside your class.
You also need to put the assignment of the array inside a method (inside your class). You could also place the assignment in the constructor.
So your code would look something like this:
package tictactoe;
import java.util.Random;
import java.util.Scanner;
public class Board {
public String[] a = new String[9];
public Board() {
a[0] = "";
}
}
You are tring to declear variable outside of class body that's not correct.
you should move your array definition inside of class and initilize it in class constructor (for example).
public class Board {
public String a[] = new String[9];
public Board() {
a[0] = "";
}
}
In java, everything has to be inside a class. You cant leave it outside the class and initialize it inside the constructor to make look more clean.
public class Board {
public String a[] = new String[9];
Board(){
a[0]=" ";
}
}
If you want to see the value initialized, then
public class Board {
public static String a[] = new String[9];
Board(){
a[0]=" ";
}
public static void main(String []args){
System.out.println(" Initialially :"+a[0]);
}
}
Everything (except the import statements) in Java MUST be inside a class. Then you need to write your code to be executed inside a method. Your declaration of an array outside a class has no meaning, because that way it's not a member of any class.
Java is not a scripting language. You cannot write code outside a class.
package tictactoe;
import java.util.Random;
import java.util.Scanner;
public class Board {
public String a[] = new String[9];
//methods here
}

Is possible to see the content of the Java String pool? [duplicate]

I wanted to print the whole string pool which contains literals and String objects added using intern() just before garbage collection.
Is there a method implicit to JDK for such operation? How can we inspect the string pool?
EDIT: The comment suggests that there may be a misunderstanding regarding what this "hack" does. It prints the strings that have been interned by (directly or indirectly) calling intern(), as described in the question. It will not print the "whole string pool", as the string pool only resides in the JVM, is filled with symbols and strings that appear during classloading and initialization, and not accessible from Java side.
NeplatnyUdaj mentioned in a comment that it might be possible to define a new java.lang.String class and sneak this into the JVM at startup. I was curious, and tried it out. And what should I say: It works!
1. Create a new project that contains the package java.lang
2. Insert a class like this into this package
package java.lang;
import java.util.LinkedHashSet;
import java.util.Set;
public class StringPool {
private static Set<String> pool = null;
public static synchronized void store(String string)
{
try
{
if (pool == null)
{
pool = new LinkedHashSet<String>();
}
pool.add(string);
}
catch (Exception e)
{
// Ignore
}
}
public static synchronized Set<String> getPool()
{
return new LinkedHashSet<String>(pool);
}
}
3. Copy & Paste the original java.lang.String class into this package. Surprisingly, this works without many problems. It will complain about a single function, namely a call to
h = sun.misc.Hashing.murmur3_32(HASHING_SEED, value, 0, value.length);
that can safely be replaced with
h = 0;
4. Change the String#intern() method of the new String class. Originally, this is a native method. It can be replaced with something like
public String intern()
{
StringPool.store(this);
return this;
}
5. Create a .JAR file from this project, and store it, for example, as newString.jar
6. Create another project with a test class that generates/contains/uses some strings. (that should be easy) and compile this class, which may be named NewStringTest
7. Launch the test program with the modified string class:
java -Xbootclasspath:newString.jar;C:\jre\lib\rt.jar NewStringTest
The StringPool#getPool() method can then be used to obtain the pool containing the interned strings.
I just tested this with the following class, which manually creates some strings, and some Swing components (which can be expected to contain some strings):
import java.lang.reflect.InvocationTargetException;
import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
public class NewStringTest
{
public static void main(String[] args)
{
generateSomeStrings();
System.out.println(StringPool.getPool());
}
private static void generateSomeStrings()
{
String s = "This is some test string";
for (int i=0; i<10; i++)
{
String t = s + i;
t.intern();
}
try
{
SwingUtilities.invokeAndWait(new Runnable()
{
#Override
public void run() {
JFrame frame = new JFrame();
JTable table = new JTable();
}
});
}
catch (InvocationTargetException e)
{
e.printStackTrace();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
And the output is
[hashSeed, value, buf, J, D, Z, seed, segmentShift, segmentMask,
segments, state, head, tail, waitStatus, next, Ljava/lang/String;,
I, [C, [J, Ljava/util/Hashtable;, Ljava/security/PermissionCollection;,
Ljava/util/Vector;, Ljava/lang/Class;, main, This is some test string0,
This is some test string1, This is some test string2,
This is some test string3, This is some test string4,
This is some test string5, This is some test string6,
This is some test string7, This is some test string8,
This is some test string9, INSTANCE, es, , ES, sv, SE,
values, Ljava/lang/Object;, [Ljava/awt/Component;,
Ljava/awt/LayoutManager;, Ljava/awt/LightweightDispatcher;,
Ljava/awt/Dimension;, createUI, invoke, VK_F10,
VK_CONTEXT_MENU, VK_SPACE, VK_LEFT, VK_KP_LEFT,
VK_RIGHT, VK_KP_RIGHT, VK_ESCAPE, VK_C, VK_V, VK_X,
VK_COPY, VK_PASTE, VK_CUT, VK_INSERT, VK_DELETE,
VK_DOWN, VK_KP_DOWN, VK_UP, VK_KP_UP, VK_HOME, VK_END,
VK_PAGE_UP, VK_PAGE_DOWN, VK_TAB, VK_ENTER, VK_A,
VK_SLASH, VK_BACK_SLASH, VK_F2, VK_F8]
http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#finalize%28%29 , So the GC calls finalize method before clean-up any of the objects.
So the finalize method in String is also getting called. But sadly String is a final class and you cannot override it. (Why is String class declared final in Java?)
But If you really want to get this thing to be worked, then you need to create your own string object named something else, but inner behaviour will keep all the strings functions.
And for a guaranteed GC try this : http://code.google.com/p/jlibs/wiki/GarbageCollection

Calling parent method from within the parent class

Here's an excerpt from my code
package dictionary;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.regex.*;
public class IntelliCwDB extends CwDB {
public IntelliCwDB(String filename) {
super(filename);
}
#Override
public void add(String word, String clue) {
System.out.println("inelli");
}
}
And CwDB...
package dictionary;
import java.util.LinkedList;
import java.io.*;
import java.util.Scanner;
public class CwDB {
protected LinkedList<Entry> dict;
public CwDB(String filename) {
dict = new LinkedList<Entry>();
createDB(filename);
}
public void add(String word, String clue) {
System.out.println("cwdb");
dict.add(new Entry(word, clue));
}
protected void createDB(String filename) {
try {
BufferedReader f = new BufferedReader(new FileReader(filename));
while (f.ready()) {
this.add(f.readLine(), f.readLine());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
In the main() part I create a new IntelliCwDB object, which fires the execution of createDB().
The problem is that I want CwDB.createDB() to use it's own CwDB.add() method, not the one from IntelliCwDB. Is there any other neat solution than creating CwDB separately, then passing it into the constructor of IntelliCwDB just to rewrite the LinkedList<Entry> dict database?
You experienced one of the reasons why one should not call virtual methods from a constructor. For more details on this, see Effective Java 2nd Edition, Item 17: Design and document for inheritance or else prohibit it.
The simplest solution to your problem would be to split the base class method into a nonvirtual (final and/or private) one, and another, virtual, method, which calls the former in the base class implementation.
#aioobe was faster to provide an example to this :-)
You could solve it like this:
Create a private (or final) version of the CwDB.add, lets call it privateAdd.
Let the old add method in CwDB call this method instead.
Whenever you want to be sure that the CwDB-version of add is used, you simply call privateAdd instead.
Sample code
public class CwDB {
// ...
public void add(String word, String clue) {
privateAdd(word, clue);
}
private void privateAdd(String word, String clue) {
System.out.println("cwdb");
dict.add(new Entry(word, clue));
}
protected void createDB(String filename) {
// ...
// "Calling parent method from within the parent class" :-)
this.privateAdd(f.readLine(), f.readLine());
// ...
}
// ...
}
As #Péter Török correctly points out: You should never call a virtual method (directly or indirectly) from within a constructor. The reason is simple: The sub-class will get to run code before its super class (and itself) is initialized properly. (Whether or not it applies in this particular example stands to reason though.)
I would move the add method to addInternal in CwDB, and make a new add which calls addInternal. Then in the createDB method, call addInternal to get the correct method.
Eg.
class CwDB {
..
private void addInternal(String word, String clue) {
..
}
public void add(String word, String clue) {
addInternal(word, clue);
}
public void createDB(String filename) {
..
addInternal(w, c);
..
}
}

Categories

Resources