Getting random lines from Trove (TObjectIntHashMap)? - java

Is there a way to get random lines from a Trove (TObjectIntHashMap)? I'm using Random to test how fast a Trove can seek/load 10,000 lines. Specifically, I'd like to pass in a random integer and have the Trove seek/load that line. I've tried using the get() method, but it requires that I pass a string rather than a random int. I've also considered using keys() to return an array and reading from that array, but that would defeat the purpose as I wouldn't be reading directly from the Trove. Here's my code:
import java.io.IOException;
import java.util.List;
import java.util.Random;
import com.comScore.TokenizerTests.Methods.TokenizerUtilities;
import gnu.trove.TObjectIntHashMap;
public class Trove {
public static TObjectIntHashMap<String> lines = new TObjectIntHashMap<String>();
public static void TroveMethod(List<String> fileInArrayList)
throws IOException {
TObjectIntHashMap<String> lines = readToTrove(fileInArrayList);
TokenizerUtilities.writeOutTrove(lines);
}
public static TObjectIntHashMap<String> readToTrove(
List<String> fileInArrayList) {
int lineCount = 0;
for (int i = 0; i < fileInArrayList.size(); i++) {
lines.adjustOrPutValue(fileInArrayList.get(i), 1, 1);
lineCount++;
}
TokenizerUtilities.setUrlInput(lineCount);
return lines;
}
public static void loadRandomMapEntries() {
Random rnd = new Random(lines.size());
int loadCount = 10000;
for (int i = 0; i < loadCount; i++) {
lines.get(rnd);
}
TokenizerUtilities.setLoadCount(loadCount);
}
}
The method in question is loadRandomMapEntries(), specifically the for-loop. Any help is appreciated. Thanks!

I would:
Create an array of the values you want to insert.
Loop through the array and insert those keys.
Pick a random index from the array and do the lookup for that key.
There are benchmarks that come bundled with Trove that essentially do that already, so you could take a look at those.
Keep in mind that benchmarking is tricky to get right. I'd recommend that you use a framework like JMH for your benchmarking and be sure to always test in your application to see real-world performance.

Related

What is the fastest way to fill an ArrayList with null in java?

I want a List of n Sets of Integers and initially this list should be filled with null.
A lot of the Sets will be initialised later, and some will remain null.
I have tried different methods to implement this, some of them are included here:
List<HashSet<Integer>> List_of_Sets = Arrays.asList(new HashSet[n]);
ArrayList<HashSet<Integer>> List_of_Sets = new ArrayList<>(n);
while(n-- > 0) List_of_Sets.add(null);
Is there a faster way to do this?
For clarification an example for arrays would be Arrays.fill() used to be slower than:
/*
* initialize a smaller piece of the array and use the System.arraycopy
* call to fill in the rest of the array in an expanding binary fashion
*/
public static void bytefill(byte[] array, byte value) {
int len = array.length;
if (len > 0){
array[0] = value;
}
//Value of i will be [1, 2, 4, 8, 16, 32, ..., len]
for (int i = 1; i < len; i += i) {
System.arraycopy(array, 0, array, i, ((len - i) < i) ? (len - i) : i);
}
}
^above code is from Ross Drew's answer to Fastest way to set all values of an array?
Is there a faster way to do this?
As far as I am aware, no. Certainly, there is no easy way that is faster.
Based on how it works, I think (but I have not tested) that the Arrays.asList(new HashSet[n]) should be the fastest solution.
It would be possible to implement a custom List implementation that is like an ArrayList but is pre-initialized to N null values. But under the hood the initialization will be pretty much identical with what happens in the List implementation that asList returns. So I doubt that any performance improvements would be significant ... or worth the effort.
If you want to be sure of this, you could write a benchmark of the various options. However, I don't think this is the right approach in this case.
Instead I would recommend benchmarking and profiling your entire application to determine if operations on this list are a real performance hotspot.
If it is not a hotspot, my recommendation would be to just use the Arrays.asList approach and spend your time on something more important.
If it is a hotspot, you should consider replacing the List with an array. From your earlier description it seemed you are going to use the List like an array; i.e. using positional get and set operations, and no operations that change the list size. If that is the case, then using a real array should be more efficient. It saves memory, and avoids a level of indirection and (possibly) some bounds checking.
One reason not to do this would be if you needed to pass the array to some other code that requires a List.
If resizing is not important to you then implementing your own list might be fast. It might also be buggy. It would at least be interesting to benchmark compared to Java's lists. One strange effect that you might see is that standard lists might be optimised by the JIT sooner, as they could be used internally by Java's standard library.
Here is my attempt, although I suggest you don't use it. Use a standard list implementation instead.
import java.util.*;
public class FastListOfNullsDemo {
public static void main(String[] args) {
Set<Integer>[] arr = new Set[100_000]; // all set to null by default.
List<Set<Integer>> myList = new ArrayBackedList<>(arr);
myList.set(3, new TreeSet<Integer>());
myList.get(3).add(5);
myList.get(3).add(4);
myList.get(3).add(3);
myList.get(3).add(2);
myList.get(3).add(1);
// Let's just print some because 100,000 is a lot!
for (int i = 0; i < 10; i++) {
System.out.println(myList.get(i));
}
}
}
class ArrayBackedList<T> extends AbstractList<T> {
private final T[] arr;
ArrayBackedList(T[] arr) {
this.arr = arr;
}
#Override
public T get(int index) {
return arr[index];
}
#Override
public int size() {
return arr.length;
}
#Override
public T set(int index, T value) {
T result = arr[index];
arr[index] = value;
return result;
}
}
Another possibility would be implementing an always-null, fixed-size list. Use that to initialise the ArrayList. I won't promise that it is fast but you could try it out.
import java.util.*;
public class FastListOfNullsDemo {
public static void main(String[] args) {
List<Set<Integer>> allNull = new NullList<>(100_000);
List<Set<Integer>> myList = new ArrayList<>(allNull);
myList.set(3, new TreeSet<Integer>());
myList.get(3).add(5);
myList.get(3).add(4);
myList.get(3).add(3);
myList.get(3).add(2);
myList.get(3).add(1);
System.out.println(myList.size());
// Let's just print some because 100,000 is a lot!
for (int i = 0; i < 10; i++) {
System.out.println(myList.get(i));
}
}
}
class NullList<T> extends AbstractList<T> {
private int count;
NullList(int count) {
this.count = count;
}
#Override
public T get(int index) {
return null;
}
#Override
public int size() {
return count;
}
}

What is to be used Singly linked list or Array in the scoreboard code?

I'm creating a program in java to store top 10 highest scores. So, i'm using Array in it. I have question in my mind whether what is to be used singly linked list or array in the program to avoid complexity of the code and make program more efficient.
private int numEntries = 0;
private GameEntry[] board;
public Scoreboard(int capacity){
board = new GameEntry[capacity];
}
public void add(GameEntry e){
int newScore = e.getScore();
if(numEntries<board.length||newScore>board[numEntries-1].getScore()){
if(numEntries<board.length){
numEntries++;
}
int j=numEntries-1;
while(j>0&&board[j-1].getScore()<newScore){
board[j]=board[j-1];
j--;
}
board[j]=e;
}
}
In such cases no need to think too much about performance (unless it is huge numbers), you should write as clear as possible, understandable code. Later you may tune it, but first make sure it logically correct and you really need performance improvement.
Also you don't need to implement sorting, use existing utilities.
I would do it like this:
List<GameEntry> arr = new ArrayList<>();
Comparator<GameEntry> cmp = Comparator.comparingInt(a -> a.getScore());
public void add(GameEntry e) {
arr.add(e);
Collections.sort(arr, cmp.reversed());
while(arr.size() > capacity) {
arr.remove(arr.size()-1);
}
}

How to serialise an array of 2 lists in a binary file?

I am creating a Java program that reads two text files, selects 10 words at random from each file and stores them in an array of two string lists. I have created the following code so far, however this only reads the words, it doesn't store them. I also need to serialize the array of 2 lists in a binary file. How can this be done? Some help with this would be greatly appreciated!
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;
import static java.nio.file.StandardOpenOption.CREATE;
public class RandomWordGenerator {
public static void main(String[] args) throws IOException {
Path outputFile = Paths.get("output.txt");
ArrayList<String> randomWords1 = randomWordsFromFile("input1.txt", 10);
ArrayList<String> randomWords2 = randomWordsFromFile("input2.txt", 10);
OutputStream outputStream = new BufferedOutputStream(Files.newOutputStream(outputFile, CREATE));
System.out.println(randomWords1);
System.out.println(randomWords2);
outputStream.flush();
for (int i = 0; i < randomWords1.size(); i++) {
outputStream.write(randomWords1.get(i).getBytes());
}
for (int i = 0; i < randomWords2.size(); i++) {
outputStream.write(randomWords2.get(i).getBytes());
}
outputStream.close();
}
private static ArrayList<String> randomWordsFromFile(String fileName, int count) throws FileNotFoundException {
Scanner scanner = new Scanner(new File(fileName));
ArrayList<String> words = new ArrayList<>();
while (scanner.hasNext()) {
words.add(scanner.next());
}
return randomFromWords(words, count);
}
static private ArrayList<String> randomFromWords(ArrayList<String> words, int count) {
ArrayList<String> randomWords = new ArrayList<>();
for (int i = 0; i < count; ) {
int random = new Random().nextInt(words.size());
if (randomWords.add(words.get(random))) {
i++;
}
}
return randomWords;
}
}
Your code should read two files, select ten random words from each file and store the ten words from each file into two lists. Does it do this correctly? If it does not then fix all the errors before proceeding further. You can ask here with specific errors you cannot fix. Be sure to explain what your code is meant to do, and the error it makes to prevent it doing that.
Once everything is working correctly, go on to the next stage. Is the binary Serialization part of your requirement? If not, then I would use a simple CSV file in UTF-8, which is also a binary file (as are all files at heart). If actual Serialization is required, then read the Javadocs and tutorials on Serialization. Write some code and come back here if you cannot get it to work.

Java, return a linkedlist from a linkedlist parameter

I am trying to create a method which returns the place values of any two digits in a list that sum to zero. Where I am getting stuck is: creating the return method type, choosing the appropriate parameter to pass, and creating an empty list which holds the values to return.
Any help would be greatly appreciated!!
public class TwoSums {
public LinkedList<Integer> sum_values(LinkedList<Integer> input){
(Above) I am trying (but not sure how) to return a linked list from the method. I want the parameter to be a list with values like {3,-3,0,1}. I am also unsure of what the return type should be here.
int iterator = 0;
int scanner = 0;
LinkedList positions = new LinkedList<Integer>();
(Above) I am trying to create an empty list which I can push the place values of the parameter into, if they sum to zero
while(iterator<input.length){
if (iterator + scanner !=0){
scanner ++;}
else if (iterator + scanner ==0){
//push iterator and scanner values to the linkedlist
This is probably your homework, so I will just give you some guiding thoughts; I wont do the work for you!
First of all, the return type. Thing is: you can't just return single numbers. Because, you are interested in pairs of numbers. Thus you need some class like
public class IndexPair {
private final int firstIndex;
private final int secondIndex;
public IndexPair(int first, int second) { this.firstIndex = first ...
and then your method can simply return a List<IndexPair> object. Note: if you are serious here, you would want to override the equals method for example; in order to allow for easy comparison of IndexPair objects.
And of course: Java already knows some Pair classes which could be used here; instead of inventing your own thing.
The other problem: finding those pairs. A naive solution would be:
List<IndexPair> results = new ArrayList<>();
for (int firstIndex = 0; firstIndex < input.size(); firstIndex++) {
for (int secondIndex = firstIndex+1; secondIndex < input.size(); secondIndex++) {
if (input.get(firstIndex) + input.get(secondIndex) == 0) {
results.add(new IndexPair(firstIndex, secondIndex));
As said; the above is meant to get you going. There might be some typos or subtle bugs in that code. Take it as inspiration and work with it until it does what you need!
Edit: calling your method is as as
List<IndexPair> pairs = sum_values(Arrays.asList(-3, 3, 0, 0))
for example. But please understand: that is really basic stuff. Just do some reading around Lists and arrays. Those things have been documented many many times.

getting java.lang.Object cannot be converted to java.lang.Integer

I was implementing Graph data structure in Java.
Here is my implementation:
package Graph;
import java.util.*;
import java.io.*;
public class Graphs
{
int size;
LinkedList<Integer>[] ll;
Graphs(int size)
{
this.size = size;
ll = new LinkedList[size];
for(int i=0; i<size; i++)
ll[i] = new LinkedList<Integer>();
}
public static void print(LinkedList lli)
{
for(Integer i: lli)
System.out.println(i);
//for(int i=0; i<lli.size(); i++)
// System.out.println(lli.get(i));
}
public static void addEdge(Graphs graph, int up, int to)
{
graph.ll[to].add(up);
}
public static void main(String args[])
{
int V=5;
Graphs graph = new Graphs(V);
addEdge(graph,1,2);
addEdge(graph,1,3);
addEdge(graph,2,3);
addEdge(graph,3,1);
addEdge(graph,3,2);
addEdge(graph,3,4);
addEdge(graph,4,3);
print(graph.ll[3]);
}
}
Basically I am creating an array of LinkedLists for the graph with each linked list for a vertex of the graph.
However, I am getting a java.lang.Object cannot be converted to java.lang.Integer at line number 24. Clueless as to why am I getting this error. Any suggestions as to what am I missing?
The specific issue you're having is with your print function:
public static void print(LinkedList lli){
for(Integer i: lli)
System.out.println(i);
}
LinkedList is a raw type, meaning you lose type information about what kinds of objects are stored in the list. As a general rule, raw types are a bad idea. I'm very surprised your code compiled, but suffice to say that by saying Integer i : lli you're assumming that every object within lli is an Integer when the parameter LinkedList provides no such guarantee.
To ensure that this will work, change LinkedList lli to LinkedList<Integer> lli. This means that every object in lli is an instance of Integer, thus the iteration won't fail.
When I try to run your code, my IDE warns me about the line
ll = new LinkedList[size]
Saying:
Unchecked assignment: 'java.util.LinkedList[]' to 'java.util.LinkedList< java.lang.Integer >[]'
Which indicates that something fishy is going on here.
Mixing Lists and Arrays gets a bit messy with generic typing - it's a lot easier and cleaner to just do lists of lists if you need size mutability, or a multi-dimension array if not. For your case, that argues for a ArrayList<LinkedList<Integer>> or the like.
We can fix the issues by resolving the generic issues:
import java.util.*;
import java.io.*;
public class Graphs
{
int size;
ArrayList<LinkedList<Integer>> ll;
Graphs(int size)
{
this.size = size;
ll = new ArrayList<LinkedList<Integer>>();
for(int i=0; i<size; i++)
ll.add(new LinkedList<Integer>());
}
public static void print(LinkedList<Integer> lli)
{
for(Integer i: lli)
System.out.println(i);
//for(int i=0; i<lli.size(); i++)
// System.out.println(lli.get(i));
}
public static void addEdge(Graphs graph, int up, int to)
{
graph.ll.get(to).add(up);
}
public static void main(String args[])
{
int V=5;
Graphs graph = new Graphs(V);
addEdge(graph,1,2);
addEdge(graph,1,3);
addEdge(graph,2,3);
addEdge(graph,3,1);
addEdge(graph,3,2);
addEdge(graph,3,4);
addEdge(graph,4,3);
print(graph.ll.get(3));
}
}
Declare the print method like this:
public static void print(LinkedList<Integer> lli)
Then it will know that the contents of lli are integers.
I copied your code and it didn't compile until I changed
public static void print(LinkedList lli)
to:
public static void print(LinkedList<Integer> lli)
From where it worked without problems
Also giving variables a name which starts with an upper case letter is against the naming convention. Have a look at this oracle tutorial. The last bullet point on the page states:
If the name you choose consists of only one word, spell that word in all lowercase letters. If it consists of more than one word, capitalize the first letter of each subsequent word. The names gearRatio and currentGear are prime examples of this convention.

Categories

Resources