Can IntelliJ auto complete and include simple generics? - ide

I have recently switched back to IntelliJ from Eclipse and one thing I am struggling with is the auto complete, especially when declaring Collections. *This is not a question about which IDE is better its just a question on how to perform a task if that task is possible *
In IntelliJ I type
List<String> listOfNames = new ArrayL (then key stroke **Alt Ctrl Space**)
I get
List<String> listOfNames = new ArrayList
Which saves me typing three letters, not a great saving I am sure you will agree
If I use Eclipse and use the key stroke Ctrl Space on
List<String> listOfNames = new Ar
I get this result including the generics
List<String> listOfNames = new ArrayList<String>()
I am sure I am missing something like a keystroke I can't find or a plugin I need to add.
Thanks

type
List<String> listOfNames = new //be aware of the space after new
and press crtl+shift+spacebar, magic happens!

Related

Structural Search to match method call with generic parameter

Let's say that I have a class class Foo : Base and I want to perform a certain method call with signature
public void someStuf(Iterable<? extends Base> param)
For the search template I just take as starting point the pre-existing one
$Instance$.$MethodCall$($Parameter$)
Is it possible to match a parameter of any kind Iterable of a specific Base subclass (Foo in this example)??
List<Foo> fooList = new ArrayList<>();
fooList.add(new Foo("A"));
List<Bar> barList = new ArrayList<>();
barList.add(new Bar(1));
someStuff(fooList); // find this!
someStuff(barList); // don't find this one
someStuff(Collections.singletonList(new Foo("B"))); // also match this one
I've tried several combinations without any luck, is it even possible to do?
This was previously not possible without resorting to a hack. See further below for that. Currently, the code can be found using a Type modifier.
search template
$Instance$.$MethodCall$($Parameter$)
variables
$Instance$ Count=[0,1]
$MethodCall Text=someStuff
$Parameter$ Type=Iterable<Foo>, within type hierarchy
hack
The hack previously needed used a Script modifier and a simple Type modifier on the $Parameter$ variable:
$Parameter$
Script=__context__.type.parameters[0].presentableText.contains("Foo")
Type=Iterable
The related bug report is fixed since IntelliJ IDEA 2017.3.

How can I create a nested/split column header using TornadoFx?

I'm creating a tableview that has 4 main headers, and each header has a "costs" and "units" property.
In plain JavaFx, you can add columns to columns and make this split:
TableColumn emailCol = new TableColumn("Email");
TableColumn firstEmailCol = new TableColumn("Primary");
TableColumn secondEmailCol = new TableColumn("Secondary");
emailCol.getColumns().addAll(firstEmailCol, secondEmailCol);
is it possible to do this in tornadoFX?
You create nested columns in TornadoFX using the nestedColumn builder:
nestedColumn("header1") {
column("costs", Item::costsProperty)
column("units", Item::unitsProperty)
}
In addition to creating the columns, this code also creates a valueFactory for each column :)
Another very important thing to note, is that you can do absolutely everything you can do in JavaFX within TornadoFX. TornadoFX never hides the underlying JavaFX APIs, so even if we didn't have a nestedColumn builder, you could have used your exact code above, just with Kotlin syntax, and it would just work.
If you ever hit a case where you don't know how to do something in TornadoFX, you can always use the traditional JavaFX approach to achieve the same :)

Minecraft bukkit scheduler and procedural instance naming

This question is probably pretty obvious to any person who knows how to use Bukkit properly, and I'm sorry if I missed a solution in the others, but this is really kicking my ass and I don't know what else to do, the tutorials have been utterly useless. There are really 2 things that I need help doing:
I need to learn how to create an indefinite number of instances of an object. I figure it'd be like this:
int num = 0;
public void create(){
String name = chocolate + num;
Thingy name = new Thingy();
}
So you see what I'm saying? I need to basically change the name that is given to each new instance so that it doesn't overwrite the last one when created. I swear I've looked everywhere, I've asked my Java professor and I can't get any answers.
2: I need to learn how to use the stupid scheduler, and I can't understand anything so far. Basically, when an event is detected, 2 things are called: one method which activates instantly, and one which needs to be given a 5 second delay, then called. The code is like this:
public onEvent(event e){
Thingy thing = new Thingy();
thing.method1();
thing.doOnDelay(method2(), 100 ticks);
}
Once again, I apologize if I am not giving too many specifics, but I cannot FOR THE LIFE OF ME find anything about the Bukkit event scheduler that I can understand.
DO NOT leave me links to the Bukkit official tutorials, I cannot understand them at all and it'll be a waste of an answer. I need somebody who can help me, I am a starting plugin writer.
I've had Programming I and II with focus in Java, so many basic things I know, I just need Bukkit-specific help for the second one.
The first one has had me confused since I started programming.
Ok, so for the first question I think you want to use a data structure. Depending on what you're doing, there are different data structures to use. A data structure is simply a container that you can use to store many instances of a type of object. The data structures that are available to you are:
HashMap
HashSet
TreeMap
List
ArrayList
Vector
There are more, but these are the big ones. HashMap, HashSet, and TreeMap are all part of the Map class, which is notable for it's speedy operations. To use the hashmap, you instantiate it with HashMap<KeyThing, ValueThingy> thing = new HashMap<KeyThing, ValueThing>(); then you add elements to it with thing.put(key, value). Thn when you want to get a value out of it, you just use thing.get(key) HashMaps use an algorithm that's super fast to get the values, but a consequence of this is that the HashMap doesn't store it's entries in any particular order. Therefore when you want to loop though it with a for loop, it randomly returns it's entries (Not truly random because memory and stuff). Also, it's important to note that you can only have one of each individual key. If you try to put in a key that already exists in the map, it will over-right the value for that key.
The HashSet is like a HashMap but without storing values to go with it. It's a pretty good container if all you need to use it for is to determine if an object is inside it.
The TreeMap is one of the only maps that store it's values in a particular order. You have to provide a Comparator (something that tells if an object is less than another object) so that it knows the order to put the values if it wants them to be in ascending order.
List and ArrayList are not maps. Their elements are put in with a index address. With the List, you have to specify the number of elements you're going to be putting into it. Lists do not change size. ArrayLists are like lists in that each element can be retrieved with arrayListThing.get(index) but the ArrayList can change size. You add elements to an ArrayList by arrayListThing.add(Thing).
The Vector is a lot like an ArrayList. It actually functions about the same and I'm not quite sure what the difference between them is.
At any rate, you can use these data structures to store a lot of objects by making a loop. Here's an example with a Vector.
Vector<Thing> thing = new Vector<Thing>();
int numberofthings = 100;
for(int i = 0; i < numberofthings; i++) {
thing.add(new Thing());
}
That will give you a vector full of things which you can then iterate through with
for(Thing elem:thing) {
thing.dostuff
}
Ok, now for the second problem. You are correct that you need to use the Bukkit Scheduler. Here is how:
Make a class that extends BukkitRunnable
public class RunnableThing extends BukkitRunnable {
public void run() {
//what you want to do. You have to make this method.
}
}
Then what you want to do when you want to execute that thing is you make a new BukkitTask object using your RunnableThing
BukkitTask example = new RunnableThing().runTaskLater(plugin, ticks)
You have to do some math to figure out how many ticks you want. 20 ticks = 1 second. Other than that I think that covers all your questions.

why can I only access the properties of an anonymous type when I add .toList to the end of my linq query

I'm learning LINQ and VB and just spent an hour trying to access the fields of an anonymous type defined in a linq query. The key (I learned) is to convert the query to a list before you try to iterate through it with a for loop.
How to access property of anonymous type in C#?
This does not work: edit (this compiles, but intellisense does not recognize the type)
Dim varbl=from itm in collct select New With {.n=itm.Name} 'query here
for each returnedItem in varbl
returnedItem.n 'intellisense does not pick up the property names
next
But this does:
Dim varbl=(from itm in collct select New With {.n=itm.Name}).toList
for each returnedItem in varbl
returnedItem.n 'this works
next
Can somebody explain why/what is going on? The (otherwise helpful!) post above just says it is "Because of the way the compiler works, the following then should also work once you have created the list, because the anonymous types have the same structure so they are also the same type. I don't have a compiler to hand to verify this though"
Well, I wasn't going to answer since my VB is both very rusty and pretty out of date (eh, VB6 about a decade ago). But something did seem wrong here from a .NET perspective.
Your read on the answer you link to (which is incomplete in its explanation IMO) is wrong. It's not that you need to put the anonymous object into a list, but that the querent there had been putting it into a List<object> which meant that the compiler couldn't tell what properties it had (it's dealing with an object not an object of the anonymous type in question, and object doesn't have a Checked property).
Anyway. I tried writing your initial attempt into some C# as:
private class TestType
{
public string Name{get;set;}
public TestType(string name)
{
this.Name = name;
}
}
public static void Main()
{
TestType[] collct = new TestType[]{new TestType("abc"), new TestType("def"), new TestType("xyz")};
var varbl = from itm in collct select new {n = itm.Name};
foreach(var returnedItem in varbl)
Console.WriteLine(returnedItem.n);
}
Then I compiled and decompiled as VB.NET in reflector, which had my Main as:
Public Shared Sub Main()
Dim collct As TestType() = New TestType() { New TestType("abc"), New TestType("def"), New TestType("xyz") }
Dim varbl = (From itm In collct Select New With { _
.n = itm.Name _
})
Dim returnedItem
For Each returnedItem In varbl
Console.WriteLine(returnedItem.n)
Next
End Sub
Which looks pretty much like your original, doesn't it?
Well, it works; it compiles and runs and gives me correct answers.
The only thing I can think of is that maybe IntelliSense just wasn't on the ball here. I have found that some times in the past, IntelliSense struggles to suggest the property names of anonymous types, and while I use SharpDevelop to code C# rather than VB (in whatever IDE it is that you use), this could be the case here - you actually had the correct code all along, but IntelliSense didn't realise it.
At the end of the day, IntelliSense is pretty darn good, but it's not the compiler, and it can't spend as much resources doing stuff as the compiler for risk of slowing us down while we type.
Incidentally, you should not call ToList unless you actually need a list for your purposes. Imagine if collct was a loaded-as-needed enumeration that would return thousands of objects on the back of loading something from a database or file.
If you don't call ToList, then you will start iterating through them as soon as the data for the first one arrives, and you'll only need to use memory for a handful at a time.
If you do call ToList, then program will be stuck at that line until it's loaded every single object into a massive list in memory, and only then start your For Each.
Of course, there are times when you do need to be able to move back and forward though a list, or to know the count before you iterate, and then it's certainly better to call ToList than to keep repeating the For Each, but if you don't know you need it, don't use it.

Is there a better way of filling a generic List from a SQL DataAdapter?

I have an existing application that uses Active Record for its data retrieval. It's in VB.NET (first time I'm doing VB.NET; I usually work in C#). And I'm building a method to return a List(Of T) of an object.
The current pattern uses a SQLDataAdapter to populate a datatable. I COULD add the record to the List(Of T) as I fill the datatable, but there HAS to be a better way to do this.
Any ideas? I'm not married to using SQLDataAdapter, if there's a better way that avoids it...
As you've still not had any responses...
I haven't used Active Record myself, so I don't know at what point that makes any kind of difference but it strikes me that reading into a DataTable and a List<T> is duplicating things somewhat.
How about populating the List<T> from a SqlDataReader instead? As you move through the results using Read(), create a new object from the current row and add it to the list. If you need to do it for various different types, I'd write a generic method to do it, along the lines of:
public static List<T> ToList<T>(this SqlDataReader reader,
Func<SqlDataReader, T> rowConverter)
{
List<T> ret = new List<T>();
while (reader.Read())
{
ret.Add(rowConverter(reader));
}
return ret;
}
Then you can implement the converter with a lambda expression or anonymous method.
Alternatively you could make the extension method target the command instead of the SqlDataReader - it could deal with calling ExecuteReader, converting every row and then disposing of the reader afterwards.
(It's a slightly odd signature because SqlDataReader represents both the iterator and the current row; just a quirk of the API.)
I'm probably missing something deeper though - if this doesn't help, could you explain why, perhaps as a question edit?